예제 #1
0
        public void SuccessfulDotNetRunnerExecution_ReturnsDependencyGraph()
        {
            var mockFileSystem = new MockFileSystem(new Dictionary <string, MockFileData>());

            // Arrange
            var dotNetRunner = new Mock <IDotNetRunner>();

            dotNetRunner.Setup(runner => runner.Run(It.IsAny <string>(), It.IsAny <string[]>()))
            .Returns(new RunStatus(string.Empty, string.Empty, 0))
            .Callback((string directory, string[] arguments) =>
            {
                // Grab the temp filename that was passed...
                string tempFileName = arguments[3].Replace("/p:RestoreGraphOutputPath=", string.Empty).Trim('"');

                // ... and stuff it with our dummy dependency graph
                mockFileSystem.AddFileFromEmbeddedResource(tempFileName, GetType().Assembly, "DotNetOutdated.Tests.TestData.test.dg");
            });

            var graphService = new DependencyGraphService(dotNetRunner.Object, mockFileSystem);

            // Act
            var dependencyGraph = graphService.GenerateDependencyGraph(Path);

            // Assert
            Assert.NotNull(dependencyGraph);
        }
        public void EmptySolution_ReturnsEmptyDependencyGraph()
        {
            var mockFileSystem = new MockFileSystem(new Dictionary <string, MockFileData>());

            // Arrange
            var dotNetRunner = new Mock <IDotNetRunner>();

            dotNetRunner.Setup(runner => runner.Run(It.IsAny <string>(), It.Is <string[]>(a => a[0] == "msbuild" && a[2] == "/t:Restore,GenerateRestoreGraphFile")))
            .Returns(new RunStatus(string.Empty, string.Empty, 0))
            .Callback((string directory, string[] arguments) =>
            {
                // Grab the temp filename that was passed...
                string tempFileName = arguments[3].Replace("/p:RestoreGraphOutputPath=", string.Empty).Trim('"');

                // ... and stuff it with our dummy dependency graph
                mockFileSystem.AddFileFromEmbeddedResource(tempFileName, GetType().Assembly, "DotNetOutdated.Tests.TestData.empty.dg");
            });;

            var graphService = new DependencyGraphService(dotNetRunner.Object, mockFileSystem);

            // Act
            var dependencyGraph = graphService.GenerateDependencyGraph(_solutionPath);

            // Assert
            Assert.NotNull(dependencyGraph);
            Assert.Equal(0, dependencyGraph.Projects.Count);

            dotNetRunner.Verify(runner => runner.Run(_path, It.Is <string[]>(a => a[0] == "msbuild" && a[1] == '\"' + _solutionPath + '\"' && a[2] == "/t:Restore,GenerateRestoreGraphFile")));
        }
예제 #3
0
        internal Thens ShouldContainSeedBucketProject(string projectName, string slnPath)
        {
            var dependencyGraphService = new DependencyGraphService(new DependencyGraphRunner());

            var projectNames = dependencyGraphService.GetSolutionProjectsNames(slnPath);

            projectNames.Should().Contain(projectName);

            return(this);
        }
예제 #4
0
        /// <summary>
        /// This method is called when the dependency graph service created the dependency graph.
        /// </summary>
        /// <param name="ar">The async result.</param>
        private void OnGetDependencyGraphCompleted(IAsyncResult ar)
        {
            var dispatcher = Application.Current.Dispatcher;

            if (!dispatcher.CheckAccess())
            {
                dispatcher.BeginInvoke(new Action <IAsyncResult>(OnGetDependencyGraphCompleted), ar);
                return;
            }

            bool onLoad = (bool)ar.AsyncState;

            try
            {
                Graph = DependencyGraphService.EndGetDependencyGraph(ar);

                if (Graph == null)
                {
                    RefreshHint = onLoad ? "Effective dependencies and identified anomalies are not resolved (Graph could not be created)" : "Effective dependencies and identified anomalies are not resolved (Graph could not be refreshed)";
                    return;
                }
            }
            catch (InvalidComponentException)
            {
                RefreshHint = onLoad ? "Effective dependencies and identified anomalies are not resolved (Graph could not be created)" : "Effective dependencies and identified anomalies are not resolved (Graph could not be refreshed)";
                return;
            }
            catch (DependencyServiceException)
            {
                RefreshHint = onLoad ? "Effective dependencies and identified anomalies are not resolved (Graph could not be created)" : "Effective dependencies and identified anomalies are not resolved (Graph could not be refreshed)";
                return;
            }

            var anomalies = new CompositeCollection();

            if (Graph.CircularDependencies.Any())
            {
                var collectionContainer = new CollectionContainer();
                collectionContainer.Collection = Graph.CircularDependencies;
                anomalies.Add(collectionContainer);
            }
            if (Graph.SideBySideDependencies.Any())
            {
                var collectionContainer = new CollectionContainer();
                collectionContainer.Collection = Graph.SideBySideDependencies;
                anomalies.Add(collectionContainer);
            }
            Anomalies = anomalies;
        }
예제 #5
0
        public void UnsuccessfulDotNetRunnerExecution_Throws()
        {
            var mockFileSystem = new MockFileSystem(new Dictionary <string, MockFileData>());

            // Arrange
            var dotNetRunner = new Mock <IDotNetRunner>();

            dotNetRunner.Setup(runner => runner.Run(It.IsAny <string>(), It.IsAny <string[]>()))
            .Returns(new RunStatus(string.Empty, string.Empty, 1));

            var graphService = new DependencyGraphService(dotNetRunner.Object, mockFileSystem);

            // Assert
            Assert.Throws <CommandValidationException>(() => graphService.GenerateDependencyGraph(Path));
        }
예제 #6
0
        public void UnsuccessfulDotNetRunnerExecution_ReturnsNull()
        {
            var mockFileSystem = new MockFileSystem(new Dictionary <string, MockFileData>());

            // Arrange
            var dotNetRunner = new Mock <IDotNetRunner>();

            dotNetRunner.Setup(runner => runner.Run(It.IsAny <string>(), It.IsAny <string[]>()))
            .Returns(new RunStatus(string.Empty, string.Empty, 1));

            var graphService = new DependencyGraphService(dotNetRunner.Object, mockFileSystem);

            // Act
            var dependencyGraph = graphService.GenerateDependencyGraph(Path);

            // Assert
            Assert.Null(dependencyGraph);
        }
        public void SolutionPath_ReturnsDependencyGraphForAllProjects()
        {
            var mockFileSystem = new MockFileSystem(new Dictionary <string, MockFileData>());

            // Arrange
            var dotNetRunner = new Mock <IDotNetRunner>();

            string solutionProjects = string.Join(Environment.NewLine, "Project(s)", "-----------", _project1Path, _project2Path);

            dotNetRunner.Setup(runner => runner.Run(It.IsAny <string>(), It.Is <string[]>(a => a[0] == "sln")))
            .Returns(new RunStatus(solutionProjects, string.Empty, 0));

            dotNetRunner.Setup(runner => runner.Run(It.IsAny <string>(), It.Is <string[]>(a => a[0] == "msbuild")))
            .Returns(new RunStatus(string.Empty, string.Empty, 0))
            .Callback((string directory, string[] arguments) =>
            {
                // Grab the temp filename that was passed...
                string tempFileName = arguments[3].Replace("/p:RestoreGraphOutputPath=", string.Empty).Trim('"');

                // ... and stuff it with our dummy dependency graph
                string dependencyGraphFile = arguments[1] == '\"' + _project1Path + '\"' ? "test.dg" : "empty.dg";
                mockFileSystem.AddFileFromEmbeddedResource(tempFileName, GetType().Assembly, "DotNetOutdated.Tests.TestData." + dependencyGraphFile);
            });

            mockFileSystem.AddFileFromEmbeddedResource(_project1Path, GetType().Assembly, "DotNetOutdated.Tests.TestData.MicrosoftSdk.xml");
            mockFileSystem.AddFileFromEmbeddedResource(_project2Path, GetType().Assembly, "DotNetOutdated.Tests.TestData.MicrosoftSdk.xml");

            var graphService = new DependencyGraphService(dotNetRunner.Object, mockFileSystem);

            // Act
            var dependencyGraph = graphService.GenerateDependencyGraph(_solutionPath);

            // Assert
            Assert.NotNull(dependencyGraph);
            Assert.Equal(4, dependencyGraph.Projects.Count);

            dotNetRunner.Verify(runner => runner.Run(_path, It.Is <string[]>(a => a[0] == "sln" && a[2] == "list" && a[1] == '\"' + _solutionPath + '\"')));
            dotNetRunner.Verify(runner => runner.Run(XFS.Path(@"c:\path\proj1"), It.Is <string[]>(a => a[0] == "msbuild" && a[1] == '\"' + _project1Path + '\"')));
            dotNetRunner.Verify(runner => runner.Run(XFS.Path(@"c:\path\proj2"), It.Is <string[]>(a => a[0] == "msbuild" && a[1] == '\"' + _project2Path + '\"')));
        }
        public void EmptySolution_ReturnsEmptyDependencyGraph()
        {
            var mockFileSystem = new MockFileSystem(new Dictionary <string, MockFileData>());

            // Arrange
            var dotNetRunner = new Mock <IDotNetRunner>();

            string solutionProjects = string.Join(Environment.NewLine, "Project(s)", "-----------");

            dotNetRunner.Setup(runner => runner.Run(It.IsAny <string>(), It.Is <string[]>(a => a[0] == "sln")))
            .Returns(new RunStatus(solutionProjects, string.Empty, 0));

            var graphService = new DependencyGraphService(dotNetRunner.Object, mockFileSystem);

            // Act
            var dependencyGraph = graphService.GenerateDependencyGraph(_solutionPath);

            // Assert
            Assert.NotNull(dependencyGraph);
            Assert.Equal(0, dependencyGraph.Projects.Count);

            dotNetRunner.Verify(runner => runner.Run(_path, It.Is <string[]>(a => a[0] == "sln" && a[2] == "list" && a[1] == '\"' + _solutionPath + '\"')));
            dotNetRunner.Verify(runner => runner.Run(It.IsAny <string>(), It.Is <string[]>(a => a[0] == "msbuild")), Times.Never());
        }
예제 #9
0
        // TODO: Should we use framework here
        //
        // 1. Create dgspec.json via .NET Core CLI: GenerateRestoreGraphFile target
        // 2. Load dgspec.json into DependencyGraphSpec instance/object
        // For each SDK project (ProjectStyle.PackageReference) in the graph spec
        // 3. Get assets file (project.assets.json) for the project
        // 4. Construct LockFile from assets file for the project
        static void AnalyzeProject(string projectPath, string framework)
        {
            // Graph input
            var vertices = new HashSet <Node>();
            var edges    = new HashSet <Edge>();

            var rootNuGetFramework = NuGetFramework.ParseFolder(framework); // TODO: optional filter

            // TODO: HACK...kan fjernes
            if (string.IsNullOrEmpty(projectPath))
            {
                var rootPath = GetRepoRootPath();

                //projectPath = Path.Combine(rootPath, "DotnetDependencies.sln");
                projectPath = Path.Combine(
                    Path.Combine(
                        Path.Combine(rootPath, "src"), "Deps.CLI"), "Deps.CLI.csproj");
            }

            // 'package graph' is a better word
            // Load dependency graph via nuget client tools build into msbuild (.NET Core CLI, .NET Core SDK)
            // TODO: opsatning af packageSources
            var dependencyGraphService = new DependencyGraphService();
            var dependencyGraph        = dependencyGraphService.GenerateDependencyGraph(projectPath);

            // We only support MSBuild style <PackageReference> SDK projects, where project.assets.json (lock file) is
            // generated in the RestoreOutputPath folder
            if (dependencyGraph.Projects.Any(p => p.RestoreMetadata.ProjectStyle != ProjectStyle.PackageReference))
            {
                throw new InvalidOperationException("Only SDK projects are supported.");
            }

            PackageSpec projectRoot = dependencyGraph.Projects.Single(p => Path.GetFileName(p.FilePath) == Path.GetFileName(projectPath));

            var rootNode = new ProjectReferenceNode(projectPath, projectRoot.Version.ToString(), rootNuGetFramework);

            vertices.Add(rootNode);

            var projectRootTargetFramework = projectRoot.TargetFrameworks.FirstOrDefault(tf => rootNuGetFramework.Equals(tf.FrameworkName));

            if (projectRootTargetFramework == null)
            {
                throw new InvalidOperationException(
                          $"The root project does not define the TargetFramework {rootNuGetFramework}");
            }

            //Console.WriteLine($"project: {Path.GetFileName(project.FilePath)}");
            //Console.WriteLine($"project.BaseDirectory: {Path.GetFileName(project.BaseDirectory)}");
            //Console.WriteLine($"project.Name: {project.Name}");
            //Console.WriteLine($"project.TargetFrameworks: {string.Join(", ", project.TargetFrameworks.Select(tfm => tfm.FrameworkName.GetShortFolderName()))}");
            //Console.WriteLine($"project.Version: {project.Version}");
            //Console.WriteLine($"project.RestoreMetadata.ProjectName: {project.RestoreMetadata.ProjectName}");
            //Console.WriteLine($"project.RestoreMetadata.Sources: {string.Join(", ", project.RestoreMetadata.Sources)}");
            //Console.WriteLine($"project.Dependencies: {string.Join(", ", project.Dependencies)}");


            // TODO: Path. Unique name etc...
            Console.WriteLine($"Name: {projectRoot.Name}");
            Console.WriteLine($"Version: {projectRoot.Version} ({rootNuGetFramework.GetShortFolderName()})");
            Console.WriteLine($"Framework: {rootNuGetFramework.DotNetFrameworkName}");
            Console.WriteLine($"Framework moniker: {rootNuGetFramework.GetShortFolderName()}");
            Console.WriteLine();

            Console.WriteLine("resolve project reference dependency graph");
            Console.WriteLine();

            // TODO: Path. Unique name etc...
            Console.WriteLine($"{projectRoot.Name}, v{projectRoot.Version} ({rootNuGetFramework.GetShortFolderName()})");

            //
            // First resolve project reference dependency graph
            //

            foreach (ProjectRestoreMetadataFrameworkInfo targetFramework in projectRoot.RestoreMetadata.TargetFrameworks)
            {
                // only want project references defined for the TargetFramework
                if (!rootNuGetFramework.Equals(targetFramework.FrameworkName))
                {
                    continue;
                }

                // project references of a targetFramework
                foreach (var projectRestoreReference in targetFramework.ProjectReferences)
                {
                    // TODO: PrivateAssets, ExcludeAssets, IncludeAssets
                    //dependency.ProjectPath
                    //dependency.ProjectUniqueName
                    PackageSpec projectDependency = dependencyGraph.GetProjectSpec(projectRestoreReference.ProjectUniqueName);

                    //Console.WriteLine($"({project.Name}, {Path.GetFileName(project.FilePath)}) is a project reference of ({projectRoot.Name}, {Path.GetFileName(projectRoot.FilePath)}");

                    NuGetFramework nearest          = projectDependency.GetNearestFrameworkMatching(rootNuGetFramework);
                    var            projectReference = new ProjectReferenceNode(projectDependency.FilePath, projectDependency.Version.ToString(), nearest);

                    vertices.Add(projectReference);

                    edges.Add(new Edge(rootNode, projectReference));

                    ReportProjectReferences(rootNode, projectDependency, rootNuGetFramework, dependencyGraph, 1,
                                            vertices, edges);
                }
            }

            // TODO: What about ProjectReferences...are project references converted to package specs in dgspec file??? YES,
            // and available via dependencyGraph.Projects and dependencyGraph.GetProjectSpec

            // TODO: project Closure is part of graph all ready
            // closure[0] is the root
            // closure[1..m] contains project references
            IReadOnlyList <PackageSpec> projectClosure = dependencyGraph.GetClosure(projectRoot.RestoreMetadata.ProjectUniqueName);

            Debug.Assert(ReferenceEquals(projectRoot, projectClosure[0]));

            //
            // Second, resolve package reference dependency graph of each project
            //

            Console.WriteLine();
            Console.WriteLine("resolve package reference dependency graph");
            Console.WriteLine();

            // for each csproj with PackageReference style (i.e. SDK csproj)
            foreach (PackageSpec project in dependencyGraph.Projects)
            {
                // TODO: Maybe just use the project.assets.json created by .NET Core SDK tooling
                // Generate lock file: A lock file has the package dependency graph for the project/solution/repo
                // that includes both the direct as well as transitive dependencies.
                var      lockFileService = new LockFileService();
                LockFile lockFile        = lockFileService.GetLockFile(project.FilePath, project.RestoreMetadata.OutputPath);

                // TODO: This could change our code...we can get at the project references inside one single loop
                //{
                //    // TODO: For debugging
                //    var projectDirectory = Path.GetDirectoryName(lockFile.PackageSpec.RestoreMetadata.ProjectPath);
                //    // full path to the referenced msbuild files (csproj files)
                //    var projectReferences = lockFile.Libraries
                //        .Where(library => library.MSBuildProject != null)
                //        .Select(library => Path.GetFullPath(Path.Combine(projectDirectory, library.MSBuildProject)))
                //        .ToArray();

                //    if (projectReferences.Length > 0)
                //    {
                //        Console.WriteLine($"project references {string.Join(", ", projectReferences)}");
                //    }
                //}

                NuGetFramework nearest = project.GetNearestFrameworkMatching(rootNuGetFramework);

                TargetFrameworkInformation resolvedTargetFramework =
                    project.TargetFrameworks.Single(tf => nearest.Equals(tf.FrameworkName));

                // for the root should this resolve to the rootNuGetFramework
                Console.WriteLine($"{project.Name}, v{project.Version}, ({resolvedTargetFramework.FrameworkName.GetShortFolderName()})");

                // Find the transitive closure for this tfm
                LockFileTarget lockFileTargetFramework =
                    lockFile.Targets.FirstOrDefault(t => t.TargetFramework.Equals(resolvedTargetFramework.FrameworkName));

                if (lockFileTargetFramework != null)
                {
                    // For each direct dependency
                    foreach (LibraryDependency directDependency in resolvedTargetFramework.Dependencies)
                    {
                        // Find the _resolved_ package reference
                        LockFileTargetLibrary resolvedPackageReference =
                            lockFileTargetFramework.Libraries.FirstOrDefault(library =>
                                                                             library.Name == directDependency.Name);

                        // Show transitive dependencies of this direct dependency
                        ReportLockFilePackageDependencies(resolvedPackageReference, lockFileTargetFramework, 1);
                    }
                }
            }
        }
예제 #10
0
        public AnalysisResult <CSharpSyncModels> Synchronize(string path)
        {
            _context.Init(path);

            var typesForGeneration = new List <ITypeSymbol>();

            // get all controller classes
            var controllers = ControllerHelper.GetControllers(_context.Project, _context.Compilation);

            // process controllers
            foreach (var controller in controllers)
            {
                // get all controller methods that are exposed via HTTP
                var httpMethods = ControllerHelper.GetPublicMethods(controller);

                foreach (var httpMethod in httpMethods)
                {
                    // collect unique return types
                    if (!typesForGeneration.Exists(t => t.Equals(httpMethod.ReturnType)))
                    {
                        typesForGeneration.Add(httpMethod.ReturnType);
                    }

                    // collect unique parameter types
                    foreach (var parameter in httpMethod.Parameters)
                    {
                        if (!typesForGeneration.Exists(t => t.Equals(parameter.Type)))
                        {
                            typesForGeneration.Add(parameter.Type);
                        }
                    }
                }
            }

            var namedTypes = new List <INamedTypeSymbol>();

            // process collected types
            foreach (var type in typesForGeneration)
            {
                var namedType = type as INamedTypeSymbol;

                if (!namedTypes.Exists(t => t.Equals(namedType)) && TypeHelper.IsSupportedType(type))
                {
                    namedTypes.Add(namedType);
                }

                // handle type arguments
                if (!namedType.TypeArguments.IsDefaultOrEmpty)
                {
                    // TODO: get type members recursively
                    foreach (var typeArgument in namedType.TypeArguments)
                    {
                        var namedArgument = typeArgument as INamedTypeSymbol;

                        if (!namedTypes.Exists(t => t.Equals(namedArgument)) && TypeHelper.IsSupportedType(namedArgument))
                        {
                            namedTypes.Add(namedArgument);
                        }
                    }
                }
            }

            var depGraphs = new List <DirectedSparseGraph <DependencyNode> >();

            foreach (var namedType in namedTypes)
            {
                var depGraphFactory = new DependencyGraphService();

                var graph = depGraphFactory.BuildForNamedTypeSymbol(namedType);

                var readable = graph.ToReadable();

                depGraphs.Add(graph);
            }

            var nodes       = depGraphs.SelectMany(g => g.Vertices).Distinct().ToList();
            var uniqueNodes = nodes
                              .GroupBy(n => n.NamedTypeSymbol.ContainingNamespace + "." + n.NamedTypeSymbol.Name)
                              .Select(n => n.First())
                              .ToList();

            var modelAnalyzer = new ModelAnalyzer(_context);

            var classModels = new List <CSharpClassModel>();
            var enumModels  = new List <CSharpEnumModel>();

            foreach (var node in uniqueNodes)
            {
                var symbol = node.NamedTypeSymbol;

                if (symbol.TypeKind == TypeKind.Class || symbol.TypeKind == TypeKind.Struct)
                {
                    classModels.Add(modelAnalyzer.AnalyzeClassSymbol(symbol));
                }
                else if (symbol.TypeKind == TypeKind.Enum)
                {
                    enumModels.Add(modelAnalyzer.AnalyzeEnumSymbol(symbol));
                }
            }

            var webApiAnalyzer = new WebApiAnalyzer(_context);

            var controllerModels = new List <CSharpControllerModel>();

            foreach (var controller in controllers)
            {
                controllerModels.Add(webApiAnalyzer.AnalyzeController(controller, false));
            }

            return(new AnalysisResult <CSharpSyncModels>()
            {
                Success = true,
                Value = new CSharpSyncModels()
                {
                    DataModels = new CSharpDataModels()
                    {
                        Classes = classModels,
                        Enums = enumModels
                    },
                    Controllers = controllerModels
                }
            });
        }
예제 #11
0
 /// <summary>
 /// Refreshes the specified by using the dependency graph service.
 /// </summary>
 /// <param name="onLoad">True if graph is initially created. False if graph is refreshed.</param>
 private void Refresh(bool onLoad)
 {
     DependencyGraphService.BeginGetDependencyGraph(OnGetDependencyGraphCompleted, onLoad);
 }