diff --git a/TestAssets/TestProjects/TestAppDependencyGraph/CsprojLibrary1/CsprojLibrary1.csproj b/TestAssets/TestProjects/TestAppDependencyGraph/CsprojLibrary1/CsprojLibrary1.csproj index 5c4334277..4cf4c469a 100644 --- a/TestAssets/TestProjects/TestAppDependencyGraph/CsprojLibrary1/CsprojLibrary1.csproj +++ b/TestAssets/TestProjects/TestAppDependencyGraph/CsprojLibrary1/CsprojLibrary1.csproj @@ -3,8 +3,7 @@ Library - .NETStandard - v1.5 + netstandard1.5 @@ -13,5 +12,15 @@ + + + 1.0.0-alpha-20161026-2 + All + + + 1.6.0 + + + diff --git a/TestAssets/TestProjects/TestAppDependencyGraph/CsprojLibrary2/CsprojLibrary2.csproj b/TestAssets/TestProjects/TestAppDependencyGraph/CsprojLibrary2/CsprojLibrary2.csproj index 5c4334277..4cf4c469a 100644 --- a/TestAssets/TestProjects/TestAppDependencyGraph/CsprojLibrary2/CsprojLibrary2.csproj +++ b/TestAssets/TestProjects/TestAppDependencyGraph/CsprojLibrary2/CsprojLibrary2.csproj @@ -3,8 +3,7 @@ Library - .NETStandard - v1.5 + netstandard1.5 @@ -13,5 +12,15 @@ + + + 1.0.0-alpha-20161026-2 + All + + + 1.6.0 + + + diff --git a/TestAssets/TestProjects/TestAppDependencyGraph/CsprojLibrary3/CsprojLibrary3.csproj b/TestAssets/TestProjects/TestAppDependencyGraph/CsprojLibrary3/CsprojLibrary3.csproj index 5c4334277..4cf4c469a 100644 --- a/TestAssets/TestProjects/TestAppDependencyGraph/CsprojLibrary3/CsprojLibrary3.csproj +++ b/TestAssets/TestProjects/TestAppDependencyGraph/CsprojLibrary3/CsprojLibrary3.csproj @@ -3,8 +3,7 @@ Library - .NETStandard - v1.5 + netstandard1.5 @@ -13,5 +12,15 @@ + + + 1.0.0-alpha-20161026-2 + All + + + 1.6.0 + + + diff --git a/TestAssets/TestProjects/TestAppDependencyGraph/ProjectA/Program.cs b/TestAssets/TestProjects/TestAppDependencyGraph/ProjectA/Program.cs index 320b9d49c..1d1f78b84 100644 --- a/TestAssets/TestProjects/TestAppDependencyGraph/ProjectA/Program.cs +++ b/TestAssets/TestProjects/TestAppDependencyGraph/ProjectA/Program.cs @@ -3,6 +3,7 @@ using System; using System.Diagnostics; +using TestLibrary; namespace TestApp { @@ -11,6 +12,7 @@ namespace TestApp public static int Main(string[] args) { Console.WriteLine("This string came from ProjectA"); + Console.WriteLine($"{ProjectD.GetMessage()}"); return 0; } } diff --git a/src/Microsoft.DotNet.ProjectJsonMigration/ProjectDependencyFinder.cs b/src/Microsoft.DotNet.ProjectJsonMigration/ProjectDependencyFinder.cs index 904a7993b..b82adcd2f 100644 --- a/src/Microsoft.DotNet.ProjectJsonMigration/ProjectDependencyFinder.cs +++ b/src/Microsoft.DotNet.ProjectJsonMigration/ProjectDependencyFinder.cs @@ -17,6 +17,19 @@ namespace Microsoft.DotNet.ProjectJsonMigration { internal class ProjectDependencyFinder { + public IEnumerable ResolveProjectDependencies( + IEnumerable projectContexts, + IEnumerable preResolvedProjects = null) + { + foreach (var projectContext in projectContexts) + { + foreach (var projectDependency in ResolveProjectDependencies(projectContext, preResolvedProjects)) + { + yield return projectDependency; + } + } + } + public IEnumerable ResolveProjectDependencies(string projectDir, string xprojFile = null) { var projectContexts = ProjectContext.CreateContextForEachFramework(projectDir); @@ -31,20 +44,37 @@ namespace Microsoft.DotNet.ProjectJsonMigration return ResolveProjectDependencies(projectContexts, ResolveXProjProjectDependencyNames(xproj)); } - public IEnumerable ResolveProjectDependencies( - IEnumerable projectContexts, - IEnumerable preResolvedProjects = null) + public IEnumerable ResolveAllProjectDependenciesForFramework( + ProjectDependency projectToResolve, + NuGetFramework framework, + IEnumerable preResolvedProjects=null) { - foreach (var projectContext in projectContexts) + var projects = new List { projectToResolve }; + var allDependencies = new List(); + while (projects.Count > 0) { - foreach (var projectDependency in ResolveProjectDependencies(projectContext, preResolvedProjects)) + var project = projects.First(); + projects.Remove(project); + var projectContext = + ProjectContext.CreateContextForEachFramework(project.ProjectFilePath).FirstOrDefault(); + if(projectContext == null) { - yield return projectDependency; + continue; } + + var dependencies = ResolveDirectProjectDependenciesForFramework( + projectContext.ProjectFile, + framework, + preResolvedProjects + ); + projects.AddRange(dependencies); + allDependencies.AddRange(dependencies); } + + return allDependencies; } - public IEnumerable ResolveProjectDependenciesForFramework( + public IEnumerable ResolveDirectProjectDependenciesForFramework( Project project, NuGetFramework framework, IEnumerable preResolvedProjects=null) @@ -98,7 +128,37 @@ namespace Microsoft.DotNet.ProjectJsonMigration return projectDependencies; } - public IEnumerable ResolveProjectDependencies(ProjectContext projectContext, IEnumerable preResolvedProjects=null) + internal IEnumerable ResolveXProjProjectDependencies(ProjectRootElement xproj) + { + if (xproj == null) + { + MigrationTrace.Instance.WriteLine($"{nameof(ProjectDependencyFinder)}: No xproj file given."); + return Enumerable.Empty(); + } + + return xproj.Items + .Where(i => i.ItemType == "ProjectReference") + .Where(p => p.Includes().Any( + include => string.Equals(Path.GetExtension(include), ".csproj", StringComparison.OrdinalIgnoreCase))); + } + + internal string FindXprojFile(string projectDirectory) + { + var allXprojFiles = Directory.EnumerateFiles(projectDirectory, "*.xproj", SearchOption.TopDirectoryOnly); + + if (allXprojFiles.Count() > 1) + { + MigrationErrorCodes + .MIGRATE1017($"Multiple xproj files found in {projectDirectory}, please specify which to use") + .Throw(); + } + + return allXprojFiles.FirstOrDefault(); + } + + private IEnumerable ResolveProjectDependencies( + ProjectContext projectContext, + IEnumerable preResolvedProjects=null) { preResolvedProjects = preResolvedProjects ?? new HashSet(); @@ -144,34 +204,6 @@ namespace Microsoft.DotNet.ProjectJsonMigration PathUtility.GetPathWithDirectorySeparator(p)))); } - internal IEnumerable ResolveXProjProjectDependencies(ProjectRootElement xproj) - { - if (xproj == null) - { - MigrationTrace.Instance.WriteLine($"{nameof(ProjectDependencyFinder)}: No xproj file given."); - return Enumerable.Empty(); - } - - return xproj.Items - .Where(i => i.ItemType == "ProjectReference") - .Where(p => p.Includes().Any( - include => string.Equals(Path.GetExtension(include), ".csproj", StringComparison.OrdinalIgnoreCase))); - } - - internal string FindXprojFile(string projectDirectory) - { - var allXprojFiles = Directory.EnumerateFiles(projectDirectory, "*.xproj", SearchOption.TopDirectoryOnly); - - if (allXprojFiles.Count() > 1) - { - MigrationErrorCodes - .MIGRATE1017($"Multiple xproj files found in {projectDirectory}, please specify which to use") - .Throw(); - } - - return allXprojFiles.FirstOrDefault(); - } - private Dictionary FindPossibleProjectDependencies(string projectJsonFilePath) { var projectRootDirectory = GetRootFromProjectJson(projectJsonFilePath); diff --git a/src/Microsoft.DotNet.ProjectJsonMigration/Rules/MigratePackageDependenciesAndToolsRule.cs b/src/Microsoft.DotNet.ProjectJsonMigration/Rules/MigratePackageDependenciesAndToolsRule.cs index 6ca97b185..3f1a5de38 100644 --- a/src/Microsoft.DotNet.ProjectJsonMigration/Rules/MigratePackageDependenciesAndToolsRule.cs +++ b/src/Microsoft.DotNet.ProjectJsonMigration/Rules/MigratePackageDependenciesAndToolsRule.cs @@ -244,7 +244,7 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Rules var migratedXProjDependencyPaths = csprojReferenceItems.SelectMany(p => p.Includes()); var migratedXProjDependencyNames = new HashSet(migratedXProjDependencyPaths.Select(p => Path.GetFileNameWithoutExtension( PathUtility.GetPathWithDirectorySeparator(p)))); - var projectDependencies = _projectDependencyFinder.ResolveProjectDependenciesForFramework( + var projectDependencies = _projectDependencyFinder.ResolveDirectProjectDependenciesForFramework( project, framework, preResolvedProjects: migratedXProjDependencyNames); diff --git a/src/Microsoft.DotNet.ProjectJsonMigration/Rules/MigrateProjectDependenciesRule.cs b/src/Microsoft.DotNet.ProjectJsonMigration/Rules/MigrateProjectDependenciesRule.cs index 9fcd1b4da..e40c54c5a 100644 --- a/src/Microsoft.DotNet.ProjectJsonMigration/Rules/MigrateProjectDependenciesRule.cs +++ b/src/Microsoft.DotNet.ProjectJsonMigration/Rules/MigrateProjectDependenciesRule.cs @@ -30,8 +30,9 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Rules _projectDirectory = migrationSettings.ProjectDirectory; var migratedXProjDependencyPaths = MigrateXProjProjectDependencies(migrationRuleInputs); - var migratedXProjDependencyNames = new HashSet(migratedXProjDependencyPaths.Select(p => Path.GetFileNameWithoutExtension( - PathUtility.GetPathWithDirectorySeparator(p)))); + var migratedXProjDependencyNames = new HashSet( + migratedXProjDependencyPaths.Select(p => + Path.GetFileNameWithoutExtension(PathUtility.GetPathWithDirectorySeparator(p)))); MigrateProjectJsonProjectDependencies( migrationRuleInputs.ProjectContexts, migratedXProjDependencyNames, @@ -104,8 +105,8 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Rules HashSet migratedXProjDependencyNames, ProjectRootElement outputMSBuildProject) { - var projectDependencies = _projectDependencyFinder.ResolveProjectDependenciesForFramework( - project, + var projectDependencies = _projectDependencyFinder.ResolveAllProjectDependenciesForFramework( + new ProjectDependency(project.Name, project.ProjectFilePath), framework, migratedXProjDependencyNames); diff --git a/test/Microsoft.DotNet.ProjectJsonMigration.Tests/Rules/GivenThatIWantToMigrateProjectDependencies.cs b/test/Microsoft.DotNet.ProjectJsonMigration.Tests/Rules/GivenThatIWantToMigrateProjectDependencies.cs index 973264180..346d35434 100644 --- a/test/Microsoft.DotNet.ProjectJsonMigration.Tests/Rules/GivenThatIWantToMigrateProjectDependencies.cs +++ b/test/Microsoft.DotNet.ProjectJsonMigration.Tests/Rules/GivenThatIWantToMigrateProjectDependencies.cs @@ -238,5 +238,25 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Tests migratedProjectReferenceItem.Include.Should().Be(projectReference); migratedProjectReferenceItem.Condition.Should().Be(" '$(Bar)' == 'foo' and '$(Foo)' == 'bar' "); } + + [Fact] + public void It_promotes_P2P_references_up_in_the_dependency_chain() + { + var solutionDirectory = + TestAssetsManager.CreateTestInstance("TestAppDependencyGraph", callingMethod: "p").Path; + + var appDirectory = Path.Combine(solutionDirectory, "ProjectA"); + + var projectContext = ProjectContext.Create(appDirectory, FrameworkConstants.CommonFrameworks.NetCoreApp10); + var mockProj = ProjectRootElement.Create(); + var testSettings = new MigrationSettings(appDirectory, appDirectory, "1.0.0", mockProj, null); + var testInputs = new MigrationRuleInputs(new[] {projectContext}, mockProj, mockProj.AddItemGroup(), + mockProj.AddPropertyGroup()); + new MigrateProjectDependenciesRule().Apply(testSettings, testInputs); + + var projectReferences = mockProj.Items.Where( + item => item.ItemType.Equals("ProjectReference", StringComparison.Ordinal)); + projectReferences.Count().Should().Be(7); + } } } diff --git a/test/dotnet-migrate.Tests/GivenThatIWantToMigrateTestApps.cs b/test/dotnet-migrate.Tests/GivenThatIWantToMigrateTestApps.cs index 5af89824d..5b7a78b6c 100644 --- a/test/dotnet-migrate.Tests/GivenThatIWantToMigrateTestApps.cs +++ b/test/dotnet-migrate.Tests/GivenThatIWantToMigrateTestApps.cs @@ -375,6 +375,21 @@ namespace Microsoft.DotNet.Migration.Tests VerifyAllMSBuildOutputsRunnable(projectDirectory); } + [Fact] + public void It_builds_a_migrated_app_with_a_indirect_dependency() + { + const string projectName = "ProjectA"; + var solutionDirectory = + TestAssetsManager.CreateTestInstance("TestAppDependencyGraph", callingMethod: "p").Path; + var projectDirectory = Path.Combine(solutionDirectory, projectName); + + MigrateProject(new string[] { projectDirectory }); + Restore(projectDirectory); + BuildMSBuild(projectDirectory, projectName); + + VerifyAllMSBuildOutputsRunnable(projectDirectory); + } + private void VerifyAutoInjectedDesktopReferences(string projectDirectory, string projectName, bool shouldBePresent) { if (projectName != null)