diff --git a/src/AddIns/Misc/PackageManagement/Project/PackageManagement.csproj b/src/AddIns/Misc/PackageManagement/Project/PackageManagement.csproj index cee6ae3b57..1f8d7e8de0 100644 --- a/src/AddIns/Misc/PackageManagement/Project/PackageManagement.csproj +++ b/src/AddIns/Misc/PackageManagement/Project/PackageManagement.csproj @@ -78,6 +78,7 @@ + @@ -147,6 +148,7 @@ + @@ -218,6 +220,7 @@ + diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/Design/FakePackageManagementProjectService.cs b/src/AddIns/Misc/PackageManagement/Project/Src/Design/FakePackageManagementProjectService.cs index 2c8390a1ab..af3a2d168d 100644 --- a/src/AddIns/Misc/PackageManagement/Project/Src/Design/FakePackageManagementProjectService.cs +++ b/src/AddIns/Misc/PackageManagement/Project/Src/Design/FakePackageManagementProjectService.cs @@ -114,5 +114,11 @@ namespace ICSharpCode.PackageManagement.Design } return String.Empty; } + + public FakeProjectBuilder FakeProjectBuilder = new FakeProjectBuilder(); + + public IProjectBuilder ProjectBuilder { + get { return FakeProjectBuilder; } + } } } diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/Design/FakeProjectBuilder.cs b/src/AddIns/Misc/PackageManagement/Project/Src/Design/FakeProjectBuilder.cs new file mode 100644 index 0000000000..d343f06786 --- /dev/null +++ b/src/AddIns/Misc/PackageManagement/Project/Src/Design/FakeProjectBuilder.cs @@ -0,0 +1,25 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using ICSharpCode.SharpDevelop.Project; + +namespace ICSharpCode.PackageManagement.Design +{ + public class FakeProjectBuilder : IProjectBuilder + { + public FakeProjectBuilder() + { + BuildResults = new BuildResults(); + } + + public IProject ProjectPassedToBuild; + + public BuildResults BuildResults { get; set; } + + public void Build(IProject project) + { + ProjectPassedToBuild = project; + } + } +} diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/Solution.cs b/src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/Solution.cs index e1d26cca24..81ad82c752 100644 --- a/src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/Solution.cs +++ b/src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/Solution.cs @@ -19,6 +19,7 @@ namespace ICSharpCode.PackageManagement.EnvDTE this.solution = projectService.OpenSolution; this.Projects = new Projects(projectService); this.Globals = new SolutionGlobals(this); + this.SolutionBuild = new SolutionBuild(this, projectService.ProjectBuilder); CreateProperties(); } @@ -63,10 +64,7 @@ namespace ICSharpCode.PackageManagement.EnvDTE return null; } - public global::EnvDTE.SolutionBuild SolutionBuild { - get { return new SolutionBuild(this); } - } - + public global::EnvDTE.SolutionBuild SolutionBuild { get; private set; } public global::EnvDTE.Properties Properties { get; private set; } internal Project GetStartupProject() diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/SolutionBuild.cs b/src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/SolutionBuild.cs index 67d82fc0b2..5d47d72a70 100644 --- a/src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/SolutionBuild.cs +++ b/src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/SolutionBuild.cs @@ -2,6 +2,7 @@ // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) using System; +using ICSharpCode.SharpDevelop.Project; using ICSharpCode.SharpDevelop.Project.Commands; namespace ICSharpCode.PackageManagement.EnvDTE @@ -9,14 +10,17 @@ namespace ICSharpCode.PackageManagement.EnvDTE public class SolutionBuild : MarshalByRefObject, global::EnvDTE.SolutionBuild { Solution solution; + IProjectBuilder projectBuilder; + int lastBuildInfo; public SolutionBuild() { } - public SolutionBuild(Solution solution) + public SolutionBuild(Solution solution, IProjectBuilder projectBuilder) { this.solution = solution; + this.projectBuilder = projectBuilder; } public global::EnvDTE.SolutionConfiguration ActiveConfiguration { @@ -27,11 +31,23 @@ namespace ICSharpCode.PackageManagement.EnvDTE /// Returns the number of projects that failed to build. /// public int LastBuildInfo { - get { return 0; } + get { return lastBuildInfo; } } public void BuildProject(string solutionConfiguration, string projectUniqueName, bool waitForBuildToFinish) { + Project project = solution.Projects.Item(projectUniqueName) as Project; + projectBuilder.Build(project.MSBuildProject); + UpdateLastBuildInfo(projectBuilder.BuildResults); + } + + void UpdateLastBuildInfo(BuildResults buildResults) + { + if (buildResults.ErrorCount > 0) { + lastBuildInfo = 1; + } else { + lastBuildInfo = 0; + } } public object StartupProjects { diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/IPackageManagementProjectService.cs b/src/AddIns/Misc/PackageManagement/Project/Src/IPackageManagementProjectService.cs index f6b5267be1..45da1d59bd 100644 --- a/src/AddIns/Misc/PackageManagement/Project/Src/IPackageManagementProjectService.cs +++ b/src/AddIns/Misc/PackageManagement/Project/Src/IPackageManagementProjectService.cs @@ -12,6 +12,7 @@ namespace ICSharpCode.PackageManagement { IProject CurrentProject { get; } Solution OpenSolution { get; } + IProjectBuilder ProjectBuilder { get; } event ProjectEventHandler ProjectAdded; event SolutionFolderEventHandler SolutionFolderRemoved; diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/IProjectBuilder.cs b/src/AddIns/Misc/PackageManagement/Project/Src/IProjectBuilder.cs new file mode 100644 index 0000000000..6fca66a6d2 --- /dev/null +++ b/src/AddIns/Misc/PackageManagement/Project/Src/IProjectBuilder.cs @@ -0,0 +1,18 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using ICSharpCode.SharpDevelop.Project; + +namespace ICSharpCode.PackageManagement +{ + public interface IProjectBuilder + { + BuildResults BuildResults { get; } + + /// + /// Builds the project and waits for the build to complete. + /// + void Build(IProject project); + } +} diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/PackageManagementProjectService.cs b/src/AddIns/Misc/PackageManagement/Project/Src/PackageManagementProjectService.cs index b0acff35dd..baf44547c4 100644 --- a/src/AddIns/Misc/PackageManagement/Project/Src/PackageManagementProjectService.cs +++ b/src/AddIns/Misc/PackageManagement/Project/Src/PackageManagementProjectService.cs @@ -15,6 +15,11 @@ namespace ICSharpCode.PackageManagement { public class PackageManagementProjectService : IPackageManagementProjectService { + public PackageManagementProjectService() + { + ProjectBuilder = new ProjectBuilder(); + } + public IProject CurrentProject { get { return ProjectService.CurrentProject; } } @@ -23,6 +28,8 @@ namespace ICSharpCode.PackageManagement get { return ProjectService.OpenSolution; } } + public IProjectBuilder ProjectBuilder { get; private set; } + public void RefreshProjectBrowser() { if (WorkbenchSingleton.InvokeRequired) { diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/ProjectBuilder.cs b/src/AddIns/Misc/PackageManagement/Project/Src/ProjectBuilder.cs new file mode 100644 index 0000000000..2f9559af87 --- /dev/null +++ b/src/AddIns/Misc/PackageManagement/Project/Src/ProjectBuilder.cs @@ -0,0 +1,50 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Linq; +using System.Threading; +using ICSharpCode.SharpDevelop.Gui; +using ICSharpCode.SharpDevelop.Project; +using ICSharpCode.SharpDevelop.Project.Commands; + +namespace ICSharpCode.PackageManagement +{ + public class ProjectBuilder : IProjectBuilder + { + ManualResetEvent buildCompleteEvent = new ManualResetEvent(false); + TimeSpan DefaultBuildTimeout = new TimeSpan(0, 5, 0); + + public ProjectBuilder() + { + } + + public BuildResults BuildResults { get; private set; } + + public void Build(IProject project) + { + var build = new BuildProject(project); + build.BuildComplete += BuildComplete; + buildCompleteEvent.Reset(); + WorkbenchSingleton.SafeThreadAsyncCall(() => build.Run()); + if (buildCompleteEvent.WaitOne(DefaultBuildTimeout)) { + BuildResults = build.LastBuildResults; + } else { + BuildResults = GetBuildTimeoutResult(); + } + build.BuildComplete -= BuildComplete; + } + + BuildResults GetBuildTimeoutResult() + { + var results = new BuildResults { Result = BuildResultCode.Error }; + results.Add(new BuildError(String.Empty, "Timed out waiting for build to complete.")); + return results; + } + + void BuildComplete(object sender, EventArgs e) + { + buildCompleteEvent.Set(); + } + } +} diff --git a/src/AddIns/Misc/PackageManagement/Test/Src/EnvDTE/SolutionBuildTests.cs b/src/AddIns/Misc/PackageManagement/Test/Src/EnvDTE/SolutionBuildTests.cs index 813fde117a..622d4099c2 100644 --- a/src/AddIns/Misc/PackageManagement/Test/Src/EnvDTE/SolutionBuildTests.cs +++ b/src/AddIns/Misc/PackageManagement/Test/Src/EnvDTE/SolutionBuildTests.cs @@ -2,6 +2,8 @@ // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) using System; +using ICSharpCode.PackageManagement; +using ICSharpCode.PackageManagement.Design; using ICSharpCode.PackageManagement.EnvDTE; using NUnit.Framework; using PackageManagement.Tests.Helpers; @@ -14,11 +16,13 @@ namespace PackageManagement.Tests.EnvDTE SolutionHelper solutionHelper; Solution solution; SolutionBuild solutionBuild; + FakeProjectBuilder projectBuilder; void CreateSolutionBuild() { solutionHelper = new SolutionHelper(); solution = solutionHelper.Solution; + projectBuilder = solutionHelper.FakeProjectService.FakeProjectBuilder; solutionBuild = (SolutionBuild)solution.SolutionBuild; } @@ -39,6 +43,29 @@ namespace PackageManagement.Tests.EnvDTE solutionHelper.SetActiveConfiguration(name); } + void BuildProjectResultHasBuildError() + { + var error = new ICSharpCode.SharpDevelop.Project.BuildError(); + projectBuilder.BuildResults.Add(error); + } + + void BuildProjectFails() + { + CreateSolutionBuild(@"d:\projects\MyProject\MySolution.sln"); + string projectFileName = @"d:\projects\MyProject\MyProject.csproj"; + solutionHelper.AddProjectToSolutionWithFileName("MyProject", projectFileName); + BuildProjectResultHasBuildError(); + solutionBuild.BuildProject("Debug", "MyProject.csproj", true); + } + + void BuildProjectSucceeds() + { + CreateSolutionBuild(@"d:\projects\MyProject\MySolution.sln"); + string projectFileName = @"d:\projects\MyProject\MyProject.csproj"; + solutionHelper.AddProjectToSolutionWithFileName("MyProject", projectFileName); + solutionBuild.BuildProject("Debug", "MyProject.csproj", true); + } + [Test] public void StartupProjects_SolutionHasNoProjects_ReturnsEmptyArray() { @@ -73,5 +100,72 @@ namespace PackageManagement.Tests.EnvDTE Assert.AreEqual("Debug", name); } + + [Test] + public void BuildProject_OneProjectInSolutionAndUniqueNameMatchesProject_ProjectPassedToProjectBuilder() + { + CreateSolutionBuild(@"d:\projects\MyProject\MySolution.sln"); + string projectFileName = @"d:\projects\MyProject\MyProject.csproj"; + TestableProject expectedProject = solutionHelper.AddProjectToSolutionWithFileName("MyProject", projectFileName); + + solutionBuild.BuildProject("Debug", "MyProject.csproj", true); + + Assert.AreEqual(expectedProject, projectBuilder.ProjectPassedToBuild); + } + + [Test] + public void BuildProject_ProjectIsSecondProjectInSolution_CorrectProjectPassedToProjectBuilder() + { + CreateSolutionBuild(@"d:\projects\MyProject\MySolution.sln"); + solutionHelper.AddProjectToSolution("FirstProject"); + string projectFileName = @"d:\projects\MyProject\MyProject.csproj"; + TestableProject expectedProject = solutionHelper.AddProjectToSolutionWithFileName("MyProject", projectFileName); + + solutionBuild.BuildProject("Debug", "MyProject.csproj", true); + + Assert.AreEqual(expectedProject, projectBuilder.ProjectPassedToBuild); + } + + [Test] + public void BuildProject_OneProjectInSubFolderInsideSolutionFolderAndUniqueNameMatchesProject_ProjectPassedToProjectBuilder() + { + CreateSolutionBuild(@"d:\projects\MyProject\MySolution.sln"); + string projectFileName = @"d:\projects\MyProject\SubFolder\MyProject.csproj"; + TestableProject expectedProject = solutionHelper.AddProjectToSolutionWithFileName("MyProject", projectFileName); + + solutionBuild.BuildProject("Debug", @"SubFolder\MyProject.csproj", true); + + Assert.AreEqual(expectedProject, projectBuilder.ProjectPassedToBuild); + } + + [Test] + public void LastBuildInfo_BuildProjectFails_LastBuildInfoIsOne() + { + BuildProjectFails(); + + int result = solutionBuild.LastBuildInfo; + + Assert.AreEqual(1, result); + } + + [Test] + public void LastBuildInfo_BuildProjectFails_SolutionBuildLastBuildInfoUnchangedWhenAccessedViaSolution() + { + BuildProjectFails(); + + int result = solution.SolutionBuild.LastBuildInfo; + + Assert.AreEqual(1, result); + } + + [Test] + public void LastBuildInfo_BuildProjectSucceeds_LastBuildInfoIsZero() + { + BuildProjectSucceeds(); + + int result = solution.SolutionBuild.LastBuildInfo; + + Assert.AreEqual(0, result); + } } }