Auto add referenced assemblies for desktop migration

* https://github.com/dotnet/cli/issues/4351

Auto add referenced assemblies for desktop migration. Adds the same ones
that the build for project.json does.

* Address PR comments

* Address CR comments

* Address CR comment

Use .ToList() instead of new List

* Fix a build break

Needed .noautobuild file in my test asset project

* Change the migrate test for desktop framework to windows only

* Reducing to 120 characters per line
This commit is contained in:
Justin Goshi 2016-10-18 01:02:10 +00:00 committed by GitHub
parent a6d37d25f5
commit 71666cc9b5
6 changed files with 131 additions and 11 deletions

View file

@ -0,0 +1,21 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Microsoft.CSharp.RuntimeBinder;
namespace AutoAddDesktopReferencesDuringMigrate
{
class Program
{
static void Main(string[] args)
{
var mscorlibRef = new List<int>(new int[] { 4, 5, 6 });
var systemCoreRef = mscorlibRef.ToArray().Average();
Debug.Assert(systemCoreRef == 5, "Test System assembly reference");
if (systemCoreRef != 5)
{
throw new RuntimeBinderException("Test Microsoft.CSharp assembly reference");
}
}
}
}

View file

@ -0,0 +1,11 @@
{
"version": "1.0.0-*",
"buildOptions": {
"debugType": "portable",
"emitEntryPoint": true
},
"dependencies": {},
"frameworks": {
"net451": {}
}
}

View file

@ -67,7 +67,7 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Rules
migrationRuleInputs.OutputMSBuildProject,
targetFramework.FrameworkName,
targetFramework.Dependencies,
migrationRuleInputs.ProjectXproj);
migrationRuleInputs.ProjectXproj);
}
MigrateTools(project, migrationRuleInputs.OutputMSBuildProject);
@ -125,13 +125,15 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Rules
ProjectRootElement xproj)
{
var projectDependencies = new HashSet<string>(GetAllProjectReferenceNames(project, framework, xproj));
var packageDependencies = dependencies.Where(d => !projectDependencies.Contains(d.Name));
var packageDependencies = dependencies.Where(d => !projectDependencies.Contains(d.Name)).ToList();
string condition = framework?.GetMSBuildCondition() ?? "";
var itemGroup = output.ItemGroups.FirstOrDefault(i => i.Condition == condition)
?? output.AddItemGroup();
itemGroup.Condition = condition;
AutoInjectImplicitProjectJsonAssemblyReferences(framework, packageDependencies);
foreach (var packageDependency in packageDependencies)
{
MigrationTrace.Instance.WriteLine(packageDependency.Name);
@ -165,6 +167,31 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Rules
}
}
private void AutoInjectImplicitProjectJsonAssemblyReferences(NuGetFramework framework,
IList<ProjectLibraryDependency> packageDependencies)
{
if (framework?.IsDesktop() ?? false)
{
InjectAssemblyReferenceIfNotPresent("System", packageDependencies);
if (framework.Version >= new Version(4, 0))
{
InjectAssemblyReferenceIfNotPresent("Microsoft.CSharp", packageDependencies);
}
}
}
private void InjectAssemblyReferenceIfNotPresent(string dependencyName,
IList<ProjectLibraryDependency> packageDependencies)
{
if (!packageDependencies.Any(dep => string.Equals(dep.Name, dependencyName, StringComparison.OrdinalIgnoreCase)))
{
packageDependencies.Add(new ProjectLibraryDependency
{
LibraryRange = new LibraryRange(dependencyName, LibraryDependencyTarget.Reference)
});
}
}
private string ReadLibraryIncludeFlags(LibraryIncludeFlags includeFlags)
{
if ((includeFlags ^ LibraryIncludeFlags.All) == 0)

View file

@ -200,6 +200,39 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Tests
net451Import.Value.Split(';').Should().BeEquivalentTo($"$({importPropertyName})", "netstandard1.3");
}
[Fact]
public void It_auto_add_desktop_references_during_migrate()
{
var mockProj = RunPackageDependenciesRuleOnPj(@"
{
""frameworks"": {
""net35"" : {},
""net4"" : {},
""net451"" : {}
}
}");
var itemGroup = mockProj.ItemGroups.Where(i => i.Condition == " '$(TargetFramework)' == 'net451' ");
itemGroup.Should().HaveCount(1);
itemGroup.First().Items.Should().HaveCount(2);
var items = itemGroup.First().Items.ToArray();
items[0].Include.Should().Be("System");
items[1].Include.Should().Be("Microsoft.CSharp");
itemGroup = mockProj.ItemGroups.Where(i => i.Condition == " '$(TargetFramework)' == 'net40' ");
itemGroup.Should().HaveCount(1);
itemGroup.First().Items.Should().HaveCount(2);
items = itemGroup.First().Items.ToArray();
items[0].Include.Should().Be("System");
items[1].Include.Should().Be("Microsoft.CSharp");
itemGroup = mockProj.ItemGroups.Where(i => i.Condition == " '$(TargetFramework)' == 'net35' ");
itemGroup.Should().HaveCount(1);
itemGroup.First().Items.Should().HaveCount(1);
items = itemGroup.First().Items.ToArray();
items[0].Include.Should().Be("System");
}
private void EmitsPackageReferences(ProjectRootElement mockProj, params Tuple<string, string, string>[] packageSpecs)
{
foreach (var packageSpec in packageSpecs)

View file

@ -1,18 +1,12 @@
using Microsoft.Build.Construction;
using Microsoft.DotNet.ProjectJsonMigration;
using Microsoft.DotNet.ProjectModel;
using Microsoft.DotNet.TestFramework;
using Microsoft.DotNet.Tools.Test.Utilities;
using NuGet.Frameworks;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Xunit;
using FluentAssertions;
using System.IO;
using System.Runtime.InteropServices;
using Microsoft.DotNet.Tools.Common;
using Microsoft.DotNet.Cli;
using Microsoft.DotNet.Tools.Migrate;
using Build3Command = Microsoft.DotNet.Tools.Test.Utilities.Build3Command;
using BuildCommand = Microsoft.DotNet.Tools.Test.Utilities.BuildCommand;
@ -295,7 +289,6 @@ namespace Microsoft.DotNet.Migration.Tests
}
[Theory]
// https://github.com/dotnet/cli/issues/4313
[InlineData(true)]
[InlineData(false)]
public void Migration_outputs_error_when_no_projects_found(bool useGlobalJson)
@ -343,7 +336,42 @@ namespace Microsoft.DotNet.Migration.Tests
result.StdErr.Should().Contain(errorMessage);
result.StdErr.Should().Contain("Migration failed.");
}
[WindowsOnlyTheory]
[InlineData("DesktopTestProjects", "AutoAddDesktopReferencesDuringMigrate", true)]
[InlineData("TestProjects", "TestAppSimple", false)]
public void It_auto_add_desktop_references_during_migrate(string testGroup, string projectName, bool isDesktopApp)
{
var testAssetManager = GetTestGroupTestAssetsManager(testGroup);
var projectDirectory = testAssetManager.CreateTestInstance(projectName, callingMethod: "i").WithLockFiles().Path;
CleanBinObj(projectDirectory);
MigrateProject(new string[] { projectDirectory });
Restore3(projectDirectory);
BuildMSBuild(projectDirectory, projectName);
VerifyAutoInjectedDesktopReferences(projectDirectory, projectName, isDesktopApp);
VerifyAllMSBuildOutputsRunnable(projectDirectory);
}
private void VerifyAutoInjectedDesktopReferences(string projectDirectory, string projectName, bool shouldBePresent)
{
if (projectName != null)
{
projectName = projectName + ".csproj";
}
var root = ProjectRootElement.Open(Path.Combine(projectDirectory, projectName));
var autoInjectedReferences = root.Items.Where(i => i.ItemType == "Reference" && (i.Include == "System" || i.Include == "Microsoft.CSharp"));
if (shouldBePresent)
{
autoInjectedReferences.Should().HaveCount(2);
}
else
{
autoInjectedReferences.Should().BeEmpty();
}
}
private void VerifyMigration(IEnumerable<string> expectedProjects, string rootDir)
{
var migratedProjects = Directory.EnumerateFiles(rootDir, "project.json", SearchOption.AllDirectories)