add compat checks to dotnet add
This commit is contained in:
parent
79e6126b2a
commit
84e4da57cc
4 changed files with 138 additions and 10 deletions
|
@ -179,5 +179,10 @@
|
||||||
public const string SpecifiedNameExists = "Specified name {0} already exists. Please specify a different name.";
|
public const string SpecifiedNameExists = "Specified name {0} already exists. Please specify a different name.";
|
||||||
public const string SpecifiedAliasExists = "Specified alias {0} already exists. Please specify a different alias.";
|
public const string SpecifiedAliasExists = "Specified alias {0} already exists. Please specify a different alias.";
|
||||||
public const string MandatoryParameterMissing = "Mandatory parameter {0} missing for template {1}. ";
|
public const string MandatoryParameterMissing = "Mandatory parameter {0} missing for template {1}. ";
|
||||||
|
|
||||||
|
/// compatibility
|
||||||
|
public const string ProjectNotCompatibleWithFramework = "Project `{0}` is not compatible with `{1}`.";
|
||||||
|
public const string ProjectDoesNotTargetFramework = "Project `{0}` does not target `{1}`.";
|
||||||
|
public const string ProjectCouldNotBeEvaluated = "Project `{0}` could not be evaluated. Evaluation failed with following error:\n{1}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,10 @@
|
||||||
|
|
||||||
using Microsoft.Build.Construction;
|
using Microsoft.Build.Construction;
|
||||||
using Microsoft.Build.Evaluation;
|
using Microsoft.Build.Evaluation;
|
||||||
|
using Microsoft.Build.Exceptions;
|
||||||
using Microsoft.DotNet.Cli.Utils;
|
using Microsoft.DotNet.Cli.Utils;
|
||||||
using Microsoft.DotNet.Tools.Common;
|
using Microsoft.DotNet.Tools.Common;
|
||||||
|
using NuGet.Frameworks;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
@ -16,13 +18,16 @@ namespace Microsoft.DotNet.Tools
|
||||||
{
|
{
|
||||||
const string ProjectItemElementType = "ProjectReference";
|
const string ProjectItemElementType = "ProjectReference";
|
||||||
|
|
||||||
public ProjectRootElement Project { get; private set; }
|
public ProjectRootElement ProjectRoot { get; private set; }
|
||||||
public string ProjectDirectory { get; private set; }
|
public string ProjectDirectory { get; private set; }
|
||||||
|
|
||||||
|
private List<NuGetFramework> _cachedTfms = null;
|
||||||
|
private Project _cachedEvaluatedProject = null;
|
||||||
|
|
||||||
private MsbuildProject(ProjectRootElement project)
|
private MsbuildProject(ProjectRootElement project)
|
||||||
{
|
{
|
||||||
Project = project;
|
ProjectRoot = project;
|
||||||
ProjectDirectory = PathUtility.EnsureTrailingSlash(Project.DirectoryPath);
|
ProjectDirectory = PathUtility.EnsureTrailingSlash(ProjectRoot.DirectoryPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MsbuildProject FromFileOrDirectory(string fileOrDirectory)
|
public static MsbuildProject FromFileOrDirectory(string fileOrDirectory)
|
||||||
|
@ -101,17 +106,17 @@ namespace Microsoft.DotNet.Tools
|
||||||
{
|
{
|
||||||
int numberOfAddedReferences = 0;
|
int numberOfAddedReferences = 0;
|
||||||
|
|
||||||
ProjectItemGroupElement itemGroup = Project.FindUniformOrCreateItemGroupWithCondition(ProjectItemElementType, framework);
|
ProjectItemGroupElement itemGroup = ProjectRoot.FindUniformOrCreateItemGroupWithCondition(ProjectItemElementType, framework);
|
||||||
foreach (var @ref in refs.Select((r) => NormalizeSlashes(r)))
|
foreach (var @ref in refs.Select((r) => NormalizeSlashes(r)))
|
||||||
{
|
{
|
||||||
if (Project.HasExistingItemWithCondition(framework, @ref))
|
if (ProjectRoot.HasExistingItemWithCondition(framework, @ref))
|
||||||
{
|
{
|
||||||
Reporter.Output.WriteLine(string.Format(CommonLocalizableStrings.ProjectAlreadyHasAreference, @ref));
|
Reporter.Output.WriteLine(string.Format(CommonLocalizableStrings.ProjectAlreadyHasAreference, @ref));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
numberOfAddedReferences++;
|
numberOfAddedReferences++;
|
||||||
itemGroup.AppendChild(Project.CreateItemElement(ProjectItemElementType, @ref));
|
itemGroup.AppendChild(ProjectRoot.CreateItemElement(ProjectItemElementType, @ref));
|
||||||
|
|
||||||
Reporter.Output.WriteLine(string.Format(CommonLocalizableStrings.ReferenceAddedToTheProject, @ref));
|
Reporter.Output.WriteLine(string.Format(CommonLocalizableStrings.ReferenceAddedToTheProject, @ref));
|
||||||
}
|
}
|
||||||
|
@ -133,7 +138,7 @@ namespace Microsoft.DotNet.Tools
|
||||||
|
|
||||||
public IEnumerable<ProjectItemElement> GetProjectToProjectReferences()
|
public IEnumerable<ProjectItemElement> GetProjectToProjectReferences()
|
||||||
{
|
{
|
||||||
return Project.GetAllItemsWithElementType(ProjectItemElementType);
|
return ProjectRoot.GetAllItemsWithElementType(ProjectItemElementType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ConvertPathsToRelative(ref List<string> references)
|
public void ConvertPathsToRelative(ref List<string> references)
|
||||||
|
@ -166,12 +171,90 @@ namespace Microsoft.DotNet.Tools
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IEnumerable<NuGetFramework> GetTargetFrameworks()
|
||||||
|
{
|
||||||
|
if (_cachedTfms != null)
|
||||||
|
{
|
||||||
|
return _cachedTfms;
|
||||||
|
}
|
||||||
|
|
||||||
|
var project = GetEvaluatedProject();
|
||||||
|
|
||||||
|
var properties = project.AllEvaluatedProperties
|
||||||
|
.Where(p => p.Name.Equals("TargetFrameworks", StringComparison.OrdinalIgnoreCase) ||
|
||||||
|
p.Name.Equals("TargetFramework", StringComparison.OrdinalIgnoreCase))
|
||||||
|
.Select(p => p.EvaluatedValue.ToLower()).ToList();
|
||||||
|
|
||||||
|
var uniqueTfms = new HashSet<string>();
|
||||||
|
|
||||||
|
foreach (var property in properties)
|
||||||
|
{
|
||||||
|
var tfms = property
|
||||||
|
.Split(';')
|
||||||
|
.Select((tfm) => tfm.Trim())
|
||||||
|
.Where((tfm) => !string.IsNullOrEmpty(tfm));
|
||||||
|
|
||||||
|
foreach (var tfm in tfms)
|
||||||
|
{
|
||||||
|
uniqueTfms.Add(tfm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_cachedTfms = uniqueTfms.Select((frameworkString) => NuGetFramework.Parse(frameworkString)).ToList();
|
||||||
|
return _cachedTfms;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CanWorkOnFramework(NuGetFramework framework)
|
||||||
|
{
|
||||||
|
foreach (var tfm in GetTargetFrameworks())
|
||||||
|
{
|
||||||
|
if (DefaultCompatibilityProvider.Instance.IsCompatible(framework, tfm))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TargetsFramework(NuGetFramework framework)
|
||||||
|
{
|
||||||
|
foreach (var tfm in GetTargetFrameworks())
|
||||||
|
{
|
||||||
|
if (framework.Equals(tfm))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Project GetEvaluatedProject()
|
||||||
|
{
|
||||||
|
if (_cachedEvaluatedProject != null)
|
||||||
|
{
|
||||||
|
return _cachedEvaluatedProject;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_cachedEvaluatedProject = new Project(ProjectRoot);
|
||||||
|
}
|
||||||
|
catch (InvalidProjectFileException e)
|
||||||
|
{
|
||||||
|
throw new GracefulException(string.Format(CommonLocalizableStrings.ProjectCouldNotBeEvaluated, ProjectRoot.FullPath, e.Message));
|
||||||
|
}
|
||||||
|
|
||||||
|
return _cachedEvaluatedProject;
|
||||||
|
}
|
||||||
|
|
||||||
private int RemoveProjectToProjectReferenceAlternatives(string framework, string reference)
|
private int RemoveProjectToProjectReferenceAlternatives(string framework, string reference)
|
||||||
{
|
{
|
||||||
int numberOfRemovedRefs = 0;
|
int numberOfRemovedRefs = 0;
|
||||||
foreach (var r in GetIncludeAlternativesForRemoval(reference))
|
foreach (var r in GetIncludeAlternativesForRemoval(reference))
|
||||||
{
|
{
|
||||||
foreach (var existingItem in Project.FindExistingItemsWithCondition(framework, r))
|
foreach (var existingItem in ProjectRoot.FindExistingItemsWithCondition(framework, r))
|
||||||
{
|
{
|
||||||
ProjectElementContainer itemGroup = existingItem.Parent;
|
ProjectElementContainer itemGroup = existingItem.Parent;
|
||||||
itemGroup.RemoveChild(existingItem);
|
itemGroup.RemoveChild(existingItem);
|
||||||
|
|
|
@ -3,7 +3,9 @@
|
||||||
|
|
||||||
using Microsoft.DotNet.Cli.CommandLine;
|
using Microsoft.DotNet.Cli.CommandLine;
|
||||||
using Microsoft.DotNet.Cli.Utils;
|
using Microsoft.DotNet.Cli.Utils;
|
||||||
|
using NuGet.Frameworks;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Microsoft.DotNet.Tools.Add.ProjectToProjectReference
|
namespace Microsoft.DotNet.Tools.Add.ProjectToProjectReference
|
||||||
{
|
{
|
||||||
|
@ -51,10 +53,43 @@ namespace Microsoft.DotNet.Tools.Add.ProjectToProjectReference
|
||||||
throw new GracefulException(LocalizableStrings.SpecifyAtLeastOneReferenceToAdd);
|
throw new GracefulException(LocalizableStrings.SpecifyAtLeastOneReferenceToAdd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string frameworkString = frameworkOption.Value();
|
||||||
List<string> references = app.RemainingArguments;
|
List<string> references = app.RemainingArguments;
|
||||||
if (!forceOption.HasValue())
|
if (!forceOption.HasValue())
|
||||||
{
|
{
|
||||||
MsbuildProject.EnsureAllReferencesExist(references);
|
MsbuildProject.EnsureAllReferencesExist(references);
|
||||||
|
IEnumerable<MsbuildProject> refs = references.Select((r) => MsbuildProject.FromFile(r));
|
||||||
|
|
||||||
|
if (frameworkString == null)
|
||||||
|
{
|
||||||
|
foreach (var tfm in msbuildProj.GetTargetFrameworks())
|
||||||
|
{
|
||||||
|
foreach (var r in refs)
|
||||||
|
{
|
||||||
|
if (!r.CanWorkOnFramework(tfm))
|
||||||
|
{
|
||||||
|
throw new GracefulException(string.Format(CommonLocalizableStrings.ProjectNotCompatibleWithFramework, r.ProjectRoot.FullPath, GetFrameworkDisplayString(tfm)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var framework = NuGetFramework.Parse(frameworkString);
|
||||||
|
if (!msbuildProj.TargetsFramework(framework))
|
||||||
|
{
|
||||||
|
throw new GracefulException(string.Format(CommonLocalizableStrings.ProjectDoesNotTargetFramework, msbuildProj.ProjectRoot.FullPath, GetFrameworkDisplayString(framework)));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var r in refs)
|
||||||
|
{
|
||||||
|
if (!r.CanWorkOnFramework(framework))
|
||||||
|
{
|
||||||
|
throw new GracefulException(string.Format(CommonLocalizableStrings.ProjectNotCompatibleWithFramework, r.ProjectRoot.FullPath, GetFrameworkDisplayString(framework)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
msbuildProj.ConvertPathsToRelative(ref references);
|
msbuildProj.ConvertPathsToRelative(ref references);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +99,7 @@ namespace Microsoft.DotNet.Tools.Add.ProjectToProjectReference
|
||||||
|
|
||||||
if (numberOfAddedReferences != 0)
|
if (numberOfAddedReferences != 0)
|
||||||
{
|
{
|
||||||
msbuildProj.Project.Save();
|
msbuildProj.ProjectRoot.Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -81,5 +116,10 @@ namespace Microsoft.DotNet.Tools.Add.ProjectToProjectReference
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string GetFrameworkDisplayString(NuGetFramework framework)
|
||||||
|
{
|
||||||
|
return framework.GetShortFolderName();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ namespace Microsoft.DotNet.Tools.Remove.ProjectToProjectReference
|
||||||
|
|
||||||
if (numberOfRemovedReferences != 0)
|
if (numberOfRemovedReferences != 0)
|
||||||
{
|
{
|
||||||
msbuildProj.Project.Save();
|
msbuildProj.ProjectRoot.Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in a new issue