diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/MSBuildBasedProjectExtensions.cs b/src/AddIns/Misc/PackageManagement/Project/Src/MSBuildBasedProjectExtensions.cs
index 315832c0b0..3cd2e0b28c 100644
--- a/src/AddIns/Misc/PackageManagement/Project/Src/MSBuildBasedProjectExtensions.cs
+++ b/src/AddIns/Misc/PackageManagement/Project/Src/MSBuildBasedProjectExtensions.cs
@@ -2,7 +2,10 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
+using System.Linq;
using ICSharpCode.SharpDevelop.Project;
+using Microsoft.Build.Construction;
+using NuGet;
namespace ICSharpCode.PackageManagement
{
@@ -15,5 +18,67 @@ namespace ICSharpCode.PackageManagement
{
return project.HasProjectType(WebApplication) || project.HasProjectType(WebSite);
}
+
+ public static void AddImportIfMissing(
+ this MSBuildBasedProject project,
+ string importedProjectFile,
+ ProjectImportLocation importLocation)
+ {
+ lock (project.SyncRoot) {
+ if (project.ImportExists(importedProjectFile))
+ return;
+
+ ProjectImportElement import = AddImport(project.MSBuildProjectFile, importedProjectFile, importLocation);
+ import.Condition = GetCondition(importedProjectFile);
+ }
+ }
+
+ static ProjectImportElement AddImport(
+ ProjectRootElement projectRoot,
+ string importedProjectFile,
+ ProjectImportLocation importLocation)
+ {
+ if (importLocation == ProjectImportLocation.Top) {
+ return AddImportAtTop(projectRoot, importedProjectFile);
+ }
+ return projectRoot.AddImport(importedProjectFile);
+ }
+
+ static ProjectImportElement AddImportAtTop(ProjectRootElement projectRoot, string importedProjectFile)
+ {
+ ProjectImportElement import = projectRoot.CreateImportElement(importedProjectFile);
+ projectRoot.InsertBeforeChild(import, projectRoot.FirstChild);
+ return import;
+ }
+
+ static string GetCondition(string importedProjectFile)
+ {
+ return String.Format("Exists('{0}')", importedProjectFile);
+ }
+
+ public static bool ImportExists(this MSBuildBasedProject project, string importedProjectFile)
+ {
+ lock (project.SyncRoot) {
+ return project.FindImport(importedProjectFile) != null;
+ }
+ }
+
+ public static void RemoveImport(this MSBuildBasedProject project, string importedProjectFile)
+ {
+ lock (project.SyncRoot) {
+ ProjectImportElement import = project.FindImport(importedProjectFile);
+ if (import != null) {
+ import.Parent.RemoveChild(import);
+ }
+ }
+ }
+
+ static ProjectImportElement FindImport(this MSBuildBasedProject project, string importedProjectFile)
+ {
+ return project
+ .MSBuildProjectFile
+ .Imports
+ .FirstOrDefault(import => String.Equals(import.Project, importedProjectFile, StringComparison.OrdinalIgnoreCase));
+ }
}
}
diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/SharpDevelopProjectSystem.cs b/src/AddIns/Misc/PackageManagement/Project/Src/SharpDevelopProjectSystem.cs
index 976fe5bfdc..6f8f474a1d 100644
--- a/src/AddIns/Misc/PackageManagement/Project/Src/SharpDevelopProjectSystem.cs
+++ b/src/AddIns/Misc/PackageManagement/Project/Src/SharpDevelopProjectSystem.cs
@@ -303,12 +303,28 @@ namespace ICSharpCode.PackageManagement
public void AddImport(string targetPath, ProjectImportLocation location)
{
- throw new NotImplementedException();
+ string relativeTargetPath = GetRelativePath(targetPath);
+ project.AddImportIfMissing(relativeTargetPath, location);
+ ReevaluateProjectIfNecessary();
+ projectService.Save(project);
+ }
+
+ string GetRelativePath(string path)
+ {
+ return FileUtility.GetRelativePath(project.Directory, path);
}
public void RemoveImport(string targetPath)
{
- throw new NotImplementedException();
+ string relativeTargetPath = GetRelativePath(targetPath);
+ project.RemoveImport(relativeTargetPath);
+ ReevaluateProjectIfNecessary();
+ projectService.Save(project);
+ }
+
+ protected virtual void ReevaluateProjectIfNecessary()
+ {
+ project.ReevaluateIfNecessary();
}
}
}
diff --git a/src/AddIns/Misc/PackageManagement/Test/PackageManagement.Tests.csproj b/src/AddIns/Misc/PackageManagement/Test/PackageManagement.Tests.csproj
index 27a99869a3..9becec24d1 100644
--- a/src/AddIns/Misc/PackageManagement/Test/PackageManagement.Tests.csproj
+++ b/src/AddIns/Misc/PackageManagement/Test/PackageManagement.Tests.csproj
@@ -37,6 +37,7 @@
TRACE
+
..\RequiredLibraries\NuGet.Console.Types.dll
diff --git a/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/TestableProject.cs b/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/TestableProject.cs
index a849551d07..47b56763af 100644
--- a/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/TestableProject.cs
+++ b/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/TestableProject.cs
@@ -2,9 +2,13 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
+using System.Collections.Generic;
using System.Collections.ObjectModel;
+using System.Linq;
+
using ICSharpCode.SharpDevelop.Internal.Templates;
using ICSharpCode.SharpDevelop.Project;
+using Microsoft.Build.Construction;
namespace PackageManagement.Tests.Helpers
{
@@ -92,5 +96,20 @@ namespace PackageManagement.Tests.Helpers
dependentFile.DependentUpon = dependentUpon;
return dependentFile;
}
+
+ public ProjectImportElement GetLastMSBuildChildElement()
+ {
+ return MSBuildProjectFile.LastChild as ProjectImportElement;
+ }
+
+ public ProjectImportElement GetFirstMSBuildChildElement()
+ {
+ return MSBuildProjectFile.FirstChild as ProjectImportElement;
+ }
+
+ public ICollection GetImports()
+ {
+ return MSBuildProjectFile.Imports;
+ }
}
}
diff --git a/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/TestableSharpDevelopProjectSystem.cs b/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/TestableSharpDevelopProjectSystem.cs
index 2fa9d8a7f2..5c8ec4bf80 100644
--- a/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/TestableSharpDevelopProjectSystem.cs
+++ b/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/TestableSharpDevelopProjectSystem.cs
@@ -22,6 +22,7 @@ namespace PackageManagement.Tests.Helpers
public ReferenceAndProjectName ReferenceAndProjectNamePassedToLogAddedReferenceToProject;
public ReferenceAndProjectName ReferenceAndProjectNamePassedToLogRemovedReferenceFromProject;
public FileNameAndProjectName FileNameAndProjectNamePassedToLogAddedFileToProject;
+ public bool IsReevaluateProjectIfNecessaryCalled;
public TestableSharpDevelopProjectSystem(MSBuildBasedProject project)
: this(
@@ -82,5 +83,10 @@ namespace PackageManagement.Tests.Helpers
FileNameAndProjectNamePassedToLogAddedFileToProject =
new FileNameAndProjectName(fileName, projectName);
}
+
+ protected override void ReevaluateProjectIfNecessary()
+ {
+ IsReevaluateProjectIfNecessaryCalled = true;
+ }
}
}
diff --git a/src/AddIns/Misc/PackageManagement/Test/Src/SharpDevelopProjectSystemTests.cs b/src/AddIns/Misc/PackageManagement/Test/Src/SharpDevelopProjectSystemTests.cs
index 3a47e4bc95..ac7e898a44 100644
--- a/src/AddIns/Misc/PackageManagement/Test/Src/SharpDevelopProjectSystemTests.cs
+++ b/src/AddIns/Misc/PackageManagement/Test/Src/SharpDevelopProjectSystemTests.cs
@@ -3,10 +3,13 @@
using System;
using System.IO;
+using System.Linq;
using System.Runtime.Versioning;
using ICSharpCode.PackageManagement;
using ICSharpCode.SharpDevelop.Project;
+using Microsoft.Build.Construction;
+using NuGet;
using NUnit.Framework;
using PackageManagement.Tests.Helpers;
@@ -59,6 +62,30 @@ namespace PackageManagement.Tests
projectSystem.AddFile(fileName, (Stream)null);
}
+ void AssertLastMSBuildChildElementHasProjectAttributeValue(string expectedAttributeValue)
+ {
+ ProjectImportElement import = project.GetLastMSBuildChildElement();
+ Assert.AreEqual(expectedAttributeValue, import.Project);
+ }
+
+ void AssertLastMSBuildChildHasCondition(string expectedCondition)
+ {
+ ProjectImportElement import = project.GetLastMSBuildChildElement();
+ Assert.AreEqual(expectedCondition, import.Condition);
+ }
+
+ void AssertFirstMSBuildChildElementHasProjectAttributeValue(string expectedAttributeValue)
+ {
+ ProjectImportElement import = project.GetFirstMSBuildChildElement();
+ Assert.AreEqual(expectedAttributeValue, import.Project);
+ }
+
+ void AssertFirstMSBuildChildHasCondition(string expectedCondition)
+ {
+ ProjectImportElement import = project.GetFirstMSBuildChildElement();
+ Assert.AreEqual(expectedCondition, import.Condition);
+ }
+
[Test]
public void Root_NewInstanceCreated_ReturnsProjectDirectory()
{
@@ -833,5 +860,180 @@ namespace PackageManagement.Tests
string customTool = fileItem.CustomTool;
Assert.AreEqual(String.Empty, customTool);
}
+
+ [Test]
+ public void AddImport_FullImportFilePathAndBottomOfProject_PathRelativeToProjectAddedAsLastImportInProject()
+ {
+ CreateTestProject(@"d:\projects\MyProject\MyProject\MyProject.csproj");
+ CreateProjectSystem(project);
+ string targetPath = @"d:\projects\MyProject\packages\Foo.0.1\build\Foo.targets";
+
+ projectSystem.AddImport(targetPath, ProjectImportLocation.Bottom);
+
+ AssertLastMSBuildChildElementHasProjectAttributeValue(@"..\packages\Foo.0.1\build\Foo.targets");
+ }
+
+ [Test]
+ public void AddImport_AddImportToBottomOfProject_ImportAddedWithConditionThatChecksForExistenceOfTargetsFile()
+ {
+ CreateTestProject(@"d:\projects\MyProject\MyProject\MyProject.csproj");
+ CreateProjectSystem(project);
+ string targetPath = @"d:\projects\MyProject\packages\Foo.0.1\build\Foo.targets";
+
+ projectSystem.AddImport(targetPath, ProjectImportLocation.Bottom);
+
+ AssertLastMSBuildChildHasCondition("Exists('..\\packages\\Foo.0.1\\build\\Foo.targets')");
+ }
+
+ [Test]
+ public void AddImport_AddSameImportTwice_ImportOnlyAddedOnceToProject()
+ {
+ CreateTestProject(@"d:\projects\MyProject\MyProject\MyProject.csproj");
+ CreateProjectSystem(project);
+ string targetPath = @"d:\projects\MyProject\packages\Foo.0.1\build\Foo.targets";
+ projectSystem.AddImport(targetPath, ProjectImportLocation.Bottom);
+
+ projectSystem.AddImport(targetPath, ProjectImportLocation.Bottom);
+
+ Assert.AreEqual(1, project.GetImports().Count);
+ }
+
+ [Test]
+ public void AddImport_AddSameImportTwiceButWithDifferentCase_ImportOnlyAddedOnceToProject()
+ {
+ CreateTestProject(@"d:\projects\MyProject\MyProject\MyProject.csproj");
+ CreateProjectSystem(project);
+ string targetPath1 = @"d:\projects\MyProject\packages\Foo.0.1\build\Foo.targets";
+ string targetPath2 = @"d:\projects\MyProject\packages\Foo.0.1\BUILD\FOO.TARGETS";
+ projectSystem.AddImport(targetPath1, ProjectImportLocation.Bottom);
+
+ projectSystem.AddImport(targetPath2, ProjectImportLocation.Bottom);
+
+ Assert.AreEqual(1, project.GetImports().Count);
+ }
+
+ [Test]
+ public void AddImport_FullImportFilePathAndBottomOfProject_ProjectIsSaved()
+ {
+ CreateTestProject(@"d:\projects\MyProject\MyProject\MyProject.csproj");
+ CreateProjectSystem(project);
+ string targetPath = @"d:\projects\MyProject\packages\Foo.0.1\build\Foo.targets";
+
+ projectSystem.AddImport(targetPath, ProjectImportLocation.Bottom);
+
+ Assert.IsTrue(project.IsSaved);
+ }
+
+ [Test]
+ public void AddImport_FullImportFilePathAndBottomOfProject_ProjectIsReevaluated()
+ {
+ CreateTestProject(@"d:\projects\MyProject\MyProject\MyProject.csproj");
+ CreateProjectSystem(project);
+ string targetPath = @"d:\projects\MyProject\packages\Foo.0.1\build\Foo.targets";
+
+ projectSystem.AddImport(targetPath, ProjectImportLocation.Bottom);
+
+ Assert.IsTrue(projectSystem.IsReevaluateProjectIfNecessaryCalled);
+ }
+
+ [Test]
+ public void RemoveImport_ImportAlreadyAddedToBottomOfProject_ImportRemoved()
+ {
+ CreateTestProject(@"d:\projects\MyProject\MyProject\MyProject.csproj");
+ CreateProjectSystem(project);
+ string targetPath = @"d:\projects\MyProject\packages\Foo.0.1\build\Foo.targets";
+ projectSystem.AddImport(targetPath, ProjectImportLocation.Bottom);
+
+ projectSystem.RemoveImport(targetPath);
+
+ Assert.AreEqual(0, project.GetImports().Count);
+ }
+
+ [Test]
+ public void RemoveImport_ImportAlreadyWithDifferentCaseAddedToBottomOfProject_ImportRemoved()
+ {
+ CreateTestProject(@"d:\projects\MyProject\MyProject\MyProject.csproj");
+ CreateProjectSystem(project);
+ string targetPath1 = @"d:\projects\MyProject\packages\Foo.0.1\build\Foo.targets";
+ projectSystem.AddImport(targetPath1, ProjectImportLocation.Bottom);
+ string targetPath2 = @"d:\projects\MyProject\packages\Foo.0.1\BUILD\FOO.TARGETS";
+
+ projectSystem.RemoveImport(targetPath2);
+
+ Assert.AreEqual(0, project.GetImports().Count);
+ }
+
+ [Test]
+ public void RemoveImport_DifferentImportAdded_ExceptionNotThrown()
+ {
+ CreateTestProject(@"d:\projects\MyProject\MyProject\MyProject.csproj");
+ CreateProjectSystem(project);
+ string targetPath1 = @"d:\projects\MyProject\packages\Foo.0.1\build\Foo.targets";
+ projectSystem.AddImport(targetPath1, ProjectImportLocation.Bottom);
+ string targetPath2 = @"d:\projects\MyProject\packages\Bar.0.1\build\Bar.targets";
+
+ Assert.DoesNotThrow(() => projectSystem.RemoveImport(targetPath2));
+
+ Assert.AreEqual(1, project.GetImports().Count);
+ }
+
+ [Test]
+ public void RemoveImport_NoImportsAdded_ProjectIsSaved()
+ {
+ CreateTestProject(@"d:\projects\MyProject\MyProject\MyProject.csproj");
+ CreateProjectSystem(project);
+
+ projectSystem.RemoveImport("Unknown.targets");
+
+ Assert.IsTrue(project.IsSaved);
+ }
+
+ [Test]
+ public void RemoveImport_NoImportsAdded_ProjectIsReevaluated()
+ {
+ CreateTestProject(@"d:\projects\MyProject\MyProject\MyProject.csproj");
+ CreateProjectSystem(project);
+
+ projectSystem.RemoveImport("Unknown.targets");
+
+ Assert.IsTrue(projectSystem.IsReevaluateProjectIfNecessaryCalled);
+ }
+
+ [Test]
+ public void AddImport_AddToTopOfProject_ImportAddedAsFirstChildElement()
+ {
+ CreateTestProject(@"d:\projects\MyProject\MyProject\MyProject.csproj");
+ CreateProjectSystem(project);
+ string targetPath = @"d:\projects\MyProject\packages\Foo.0.1\build\Foo.targets";
+
+ projectSystem.AddImport(targetPath, ProjectImportLocation.Top);
+
+ AssertFirstMSBuildChildElementHasProjectAttributeValue(@"..\packages\Foo.0.1\build\Foo.targets");
+ }
+
+ [Test]
+ public void AddImport_AddImportToTopOfProject_ImportAddedWithConditionThatChecksForExistenceOfTargetsFile()
+ {
+ CreateTestProject(@"d:\projects\MyProject\MyProject\MyProject.csproj");
+ CreateProjectSystem(project);
+ string targetPath = @"d:\projects\MyProject\packages\Foo.0.1\build\Foo.targets";
+
+ projectSystem.AddImport(targetPath, ProjectImportLocation.Top);
+
+ AssertFirstMSBuildChildHasCondition("Exists('..\\packages\\Foo.0.1\\build\\Foo.targets')");
+ }
+
+ [Test]
+ public void AddImport_AddToTopOfProjectTwice_ImportAddedOnlyOnce()
+ {
+ CreateTestProject(@"d:\projects\MyProject\MyProject\MyProject.csproj");
+ CreateProjectSystem(project);
+ string targetPath = @"d:\projects\MyProject\packages\Foo.0.1\build\Foo.targets";
+ projectSystem.AddImport(targetPath, ProjectImportLocation.Top);
+
+ projectSystem.AddImport(targetPath, ProjectImportLocation.Top);
+
+ Assert.AreEqual(1, project.GetImports().Count);
+ }
}
}
diff --git a/src/Main/Base/Project/Src/Project/MSBuildBasedProject.cs b/src/Main/Base/Project/Src/Project/MSBuildBasedProject.cs
index 33fdbf3cde..cd2d36b1d8 100644
--- a/src/Main/Base/Project/Src/Project/MSBuildBasedProject.cs
+++ b/src/Main/Base/Project/Src/Project/MSBuildBasedProject.cs
@@ -335,7 +335,7 @@ namespace ICSharpCode.SharpDevelop.Project
}
}
- protected void ReevaluateIfNecessary()
+ public void ReevaluateIfNecessary()
{
using (var c = OpenCurrentConfiguration()) {
c.Project.ReevaluateIfNecessary();