From ec75e495d4bdaab101ba753f0136c4efed836290 Mon Sep 17 00:00:00 2001 From: Matt Ward Date: Sat, 8 Sep 2012 15:04:51 +0100 Subject: [PATCH] Support running custom tools on build. Add Custom Tools project options panel that can be used to enable running custom tools when a build is started just before the build executes. Project options panel allows enabling/disabling this feature and specifying which files will have their custom tools run pre-build. Configuration is stored in IProject.ProjectSpecificProperties. --- .../Project/ICSharpCode.SharpDevelop.addin | 3 + .../Project/ICSharpCode.SharpDevelop.csproj | 9 + .../ProjectCustomToolOptionsPanel.xaml | 33 +++ .../ProjectCustomToolOptionsPanel.xaml.cs | 107 +++++++ .../BeforeBuildCustomToolFileNameFilter.cs | 36 +++ .../BeforeBuildCustomToolProjectItems.cs | 51 ++++ .../Project/BeforeBuildCustomToolRunner.cs | 30 ++ .../Base/Project/Src/Project/CustomTool.cs | 3 + .../Src/Project/ProjectCustomToolOptions.cs | 46 +++ .../ICSharpCode.SharpDevelop.Tests.csproj | 4 + .../BeforeBuildCustomToolProjectItemsTests.cs | 267 ++++++++++++++++++ .../Project/ProjectCustomToolOptionsTests.cs | 212 ++++++++++++++ src/Main/Base/Test/Utils/ProjectHelper.cs | 37 +++ 13 files changed, 838 insertions(+) create mode 100644 src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/ProjectOptions/ProjectCustomToolOptionsPanel.xaml create mode 100644 src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/ProjectOptions/ProjectCustomToolOptionsPanel.xaml.cs create mode 100644 src/Main/Base/Project/Src/Project/BeforeBuildCustomToolFileNameFilter.cs create mode 100644 src/Main/Base/Project/Src/Project/BeforeBuildCustomToolProjectItems.cs create mode 100644 src/Main/Base/Project/Src/Project/BeforeBuildCustomToolRunner.cs create mode 100644 src/Main/Base/Project/Src/Project/ProjectCustomToolOptions.cs create mode 100644 src/Main/Base/Test/Project/BeforeBuildCustomToolProjectItemsTests.cs create mode 100644 src/Main/Base/Test/Project/ProjectCustomToolOptionsTests.cs create mode 100644 src/Main/Base/Test/Utils/ProjectHelper.cs diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.addin b/src/Main/Base/Project/ICSharpCode.SharpDevelop.addin index 7460ec489c..b3862756e3 100755 --- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.addin +++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.addin @@ -2273,6 +2273,9 @@ + diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj index cae14dd536..807c30b6ec 100644 --- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj +++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj @@ -257,6 +257,10 @@ DebugOptions.xaml Code + + ProjectCustomToolOptionsPanel.xaml + Code + @@ -350,6 +354,9 @@ + + + @@ -391,6 +398,7 @@ + @@ -905,6 +913,7 @@ + ProjectOptionPanel.cs diff --git a/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/ProjectOptions/ProjectCustomToolOptionsPanel.xaml b/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/ProjectOptions/ProjectCustomToolOptionsPanel.xaml new file mode 100644 index 0000000000..ebc9aa76a9 --- /dev/null +++ b/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/ProjectOptions/ProjectCustomToolOptionsPanel.xaml @@ -0,0 +1,33 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/ProjectOptions/ProjectCustomToolOptionsPanel.xaml.cs b/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/ProjectOptions/ProjectCustomToolOptionsPanel.xaml.cs new file mode 100644 index 0000000000..31ec9ebdca --- /dev/null +++ b/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/ProjectOptions/ProjectCustomToolOptionsPanel.xaml.cs @@ -0,0 +1,107 @@ +// 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.ComponentModel; +using ICSharpCode.SharpDevelop; +using ICSharpCode.SharpDevelop.Project; + +namespace ICSharpCode.SharpDevelop.Gui.OptionPanels +{ + public partial class ProjectCustomToolOptionsPanel : INotifyPropertyChanged, ICanBeDirty + { + ProjectCustomToolOptions customToolsOptions; + bool runCustomToolOnBuild; + string fileNames; + bool isDirty; + + public ProjectCustomToolOptionsPanel() + { + this.DataContext = this; + InitializeComponent(); + } + + public bool RunCustomToolOnBuild { + get { return runCustomToolOnBuild; } + set { + runCustomToolOnBuild = value; + OnChanged(); + } + } + + public string FileNames { + get { return fileNames; } + set { + fileNames = value; + OnChanged(); + } + } + + void OnChanged() + { + IsDirty = OptionsHaveChanged(); + } + + bool OptionsHaveChanged() + { + return + (runCustomToolOnBuild != customToolsOptions.RunCustomToolOnBuild) || + (fileNames != customToolsOptions.FileNames); + } + + public override void LoadOptions() + { + var project = Owner as IProject; + + customToolsOptions = new ProjectCustomToolOptions(project); + RunCustomToolOnBuild = customToolsOptions.RunCustomToolOnBuild; + FileNames = customToolsOptions.FileNames; + + OnPropertyChanged(); + } + + public override bool SaveOptions() + { + if (OptionsHaveChanged()) { + customToolsOptions.RunCustomToolOnBuild = runCustomToolOnBuild; + customToolsOptions.FileNames = fileNames; + } + IsDirty = false; + return true; + } + + public event PropertyChangedEventHandler PropertyChanged; + + void OnPropertyChanged() + { + OnPropertyChanged(null); + } + + void OnPropertyChanged(string propertyName) + { + if (PropertyChanged != null) { + PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); + } + } + + public event EventHandler IsDirtyChanged; + + void OnIsDirtyChanged() + { + if (IsDirtyChanged != null) { + IsDirtyChanged(this, new EventArgs()); + } + } + + public bool IsDirty { + get { return isDirty; } + + private set { + if (isDirty != value) { + isDirty = value; + OnIsDirtyChanged(); + } + } + } + } +} \ No newline at end of file diff --git a/src/Main/Base/Project/Src/Project/BeforeBuildCustomToolFileNameFilter.cs b/src/Main/Base/Project/Src/Project/BeforeBuildCustomToolFileNameFilter.cs new file mode 100644 index 0000000000..f94bc9796e --- /dev/null +++ b/src/Main/Base/Project/Src/Project/BeforeBuildCustomToolFileNameFilter.cs @@ -0,0 +1,36 @@ +// 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.Collections.Generic; +using System.IO; +using System.Linq; + +namespace ICSharpCode.SharpDevelop.Project +{ + public class BeforeBuildCustomToolFileNameFilter + { + List fileNames; + + public BeforeBuildCustomToolFileNameFilter(IProject project) + { + var customToolOptions = new ProjectCustomToolOptions(project); + if (customToolOptions.RunCustomToolOnBuild) { + fileNames = customToolOptions.SplitFileNames().ToList(); + } else { + fileNames = new List(); + } + } + + public bool IsMatch(string fullPath) + { + string fileNameToMatch = Path.GetFileName(fullPath); + return fileNames.Any(fileName => String.Equals(fileName, fileNameToMatch, StringComparison.OrdinalIgnoreCase)); + } + + public bool Any() + { + return fileNames.Any(); + } + } +} diff --git a/src/Main/Base/Project/Src/Project/BeforeBuildCustomToolProjectItems.cs b/src/Main/Base/Project/Src/Project/BeforeBuildCustomToolProjectItems.cs new file mode 100644 index 0000000000..b27862a81e --- /dev/null +++ b/src/Main/Base/Project/Src/Project/BeforeBuildCustomToolProjectItems.cs @@ -0,0 +1,51 @@ +// 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.Collections.Generic; +using System.Linq; +using ICSharpCode.SharpDevelop.Project; + +namespace ICSharpCode.SharpDevelop.Project +{ + public class BeforeBuildCustomToolProjectItems + { + IBuildable buildable; + + public BeforeBuildCustomToolProjectItems(IBuildable buildable) + { + this.buildable = buildable; + } + + public IEnumerable GetProjectItems() + { + return GetProjects() + .SelectMany(p => GetConfiguredCustomToolProjectItems(p)) + .ToList(); + } + + IEnumerable GetProjects() + { + IProject project = buildable as IProject; + if (project != null) { + return new IProject[] { project }; + } + + var solution = buildable as Solution; + return solution.Projects; + } + + IEnumerable GetConfiguredCustomToolProjectItems(IProject project) + { + var fileNameFilter = new BeforeBuildCustomToolFileNameFilter(project); + if (!fileNameFilter.Any()) { + return new FileProjectItem[0]; + } + + return project + .Items + .OfType() + .Where(item => fileNameFilter.IsMatch(item.Include)); + } + } +} diff --git a/src/Main/Base/Project/Src/Project/BeforeBuildCustomToolRunner.cs b/src/Main/Base/Project/Src/Project/BeforeBuildCustomToolRunner.cs new file mode 100644 index 0000000000..3532490e7c --- /dev/null +++ b/src/Main/Base/Project/Src/Project/BeforeBuildCustomToolRunner.cs @@ -0,0 +1,30 @@ +// 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.Collections.Generic; +using System.Linq; + +namespace ICSharpCode.SharpDevelop.Project +{ + public class BeforeBuildCustomToolRunner + { + public BeforeBuildCustomToolRunner() + { + ProjectService.BuildStarted += ProjectBuildStarted; + } + + void ProjectBuildStarted(object sender, BuildEventArgs e) + { + var projectItems = new BeforeBuildCustomToolProjectItems(e.Buildable); + RunCustomTool(projectItems.GetProjectItems()); + } + + void RunCustomTool(IEnumerable projectItems) + { + foreach (FileProjectItem projectItem in projectItems) { + CustomToolsService.RunCustomTool(projectItem, false); + } + } + } +} diff --git a/src/Main/Base/Project/Src/Project/CustomTool.cs b/src/Main/Base/Project/Src/Project/CustomTool.cs index 642ef117b4..bd74c298a0 100644 --- a/src/Main/Base/Project/Src/Project/CustomTool.cs +++ b/src/Main/Base/Project/Src/Project/CustomTool.cs @@ -356,6 +356,7 @@ namespace ICSharpCode.SharpDevelop.Project static Dictionary toolDict; static List customToolList; static CustomToolRun activeToolRun; + static BeforeBuildCustomToolRunner beforeBuildCustomToolRunner; internal static void Initialize() { @@ -369,6 +370,8 @@ namespace ICSharpCode.SharpDevelop.Project initialized = true; FileUtility.FileSaved += OnFileSaved; } + + beforeBuildCustomToolRunner = new BeforeBuildCustomToolRunner(); } static void OnFileSaved(object sender, FileNameEventArgs e) diff --git a/src/Main/Base/Project/Src/Project/ProjectCustomToolOptions.cs b/src/Main/Base/Project/Src/Project/ProjectCustomToolOptions.cs new file mode 100644 index 0000000000..38d01ad02a --- /dev/null +++ b/src/Main/Base/Project/Src/Project/ProjectCustomToolOptions.cs @@ -0,0 +1,46 @@ +// 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.Collections.Generic; +using System.Linq; +using ICSharpCode.Core; + +namespace ICSharpCode.SharpDevelop.Project +{ + public class ProjectCustomToolOptions + { + Properties properties; + + public ProjectCustomToolOptions(IProject project) + { + GetCustomToolProperties(project); + } + + void GetCustomToolProperties(IProject project) + { + properties = project.ProjectSpecificProperties.Get("customTool", new Properties()); + } + + public bool RunCustomToolOnBuild { + get { return properties.Get("runOnBuild", false); } + set { properties.Set("runOnBuild", value); } + } + + public string FileNames { + get { return properties.Get("fileNames", String.Empty); } + set { properties.Set("fileNames", value); } + } + + public IList SplitFileNames() + { + return + FileNames + .Replace("\r\n", ";") + .Split(';', ',') + .Select(fileName => fileName.Trim()) + .Where(fileName => !String.IsNullOrEmpty(fileName)) + .ToList(); + } + } +} diff --git a/src/Main/Base/Test/ICSharpCode.SharpDevelop.Tests.csproj b/src/Main/Base/Test/ICSharpCode.SharpDevelop.Tests.csproj index 4b51d0c4f2..a13dd8902e 100644 --- a/src/Main/Base/Test/ICSharpCode.SharpDevelop.Tests.csproj +++ b/src/Main/Base/Test/ICSharpCode.SharpDevelop.Tests.csproj @@ -87,6 +87,8 @@ + + @@ -126,6 +128,7 @@ + @@ -183,6 +186,7 @@ ICSharpCode.Core + diff --git a/src/Main/Base/Test/Project/BeforeBuildCustomToolProjectItemsTests.cs b/src/Main/Base/Test/Project/BeforeBuildCustomToolProjectItemsTests.cs new file mode 100644 index 0000000000..0e12ccaee9 --- /dev/null +++ b/src/Main/Base/Test/Project/BeforeBuildCustomToolProjectItemsTests.cs @@ -0,0 +1,267 @@ +// 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.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; + +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Project; +using ICSharpCode.SharpDevelop.Tests.Utils; +using NUnit.Framework; +using Rhino.Mocks; + +namespace ICSharpCode.SharpDevelop.Tests.Project +{ + [TestFixture] + public class BeforeBuildCustomToolProjectItemsTests + { + ProjectHelper projectHelper; + BeforeBuildCustomToolProjectItems beforeBuildCustomToolProjectItems; + Solution solution; + + IProject CreateProject(string fileName = @"d:\MyProject\MyProject.csproj") + { + projectHelper = new ProjectHelper(fileName); + return projectHelper.Project; + } + + void CreateSolution(params IProject[] projects) + { + IProjectChangeWatcher watcher = MockRepository.GenerateStub(); + solution = new Solution(watcher); + projects.ForEach(p => solution.Folders.Add(p)); + } + + void ConfigureCustomToolFileNamesForProject(string fileNames) + { + var customToolOptions = new ProjectCustomToolOptions(projectHelper.Project); + customToolOptions.FileNames = fileNames; + } + + void EnableCustomToolRunForProject() + { + SetCustomToolRunForProject(true); + } + + void SetCustomToolRunForProject(bool enabled) + { + var customToolOptions = new ProjectCustomToolOptions(projectHelper.Project); + customToolOptions.RunCustomToolOnBuild = enabled; + } + + void DisableCustomToolRunForProject() + { + SetCustomToolRunForProject(false); + } + + List GetProjectItems() + { + return beforeBuildCustomToolProjectItems.GetProjectItems().ToList(); + } + + void CreateBeforeBuildCustomToolProjectItems() + { + CreateBeforeBuildCustomToolProjectItems(projectHelper.Project as IBuildable); + } + + void CreateBeforeBuildCustomToolProjectItems(IBuildable buildable) + { + beforeBuildCustomToolProjectItems = new BeforeBuildCustomToolProjectItems(buildable); + } + + void CreateBeforeBuildCustomToolProjectItemsUsingSolution() + { + CreateBeforeBuildCustomToolProjectItems(solution as IBuildable); + } + + FileProjectItem AddFileToProject(string include) + { + var projectItem = new FileProjectItem(projectHelper.Project, ItemType.Compile, include); + projectHelper.AddProjectItem(projectItem); + return projectItem; + } + + [Test] + public void GetProjectItems_BuildSingleProjectNotConfiguredToRunCustomToolsOnBuild_ReturnsNoItems() + { + CreateProject(); + CreateBeforeBuildCustomToolProjectItems(); + + List projectItems = GetProjectItems(); + + Assert.AreEqual(0, projectItems.Count); + } + + [Test] + public void GetProjectItems_BuildSingleProjectWithOneFileMatchingCustomToolRunConfiguration_OneProjectItemReturned() + { + CreateProject(@"d:\MyProject\MyProject.csproj"); + FileProjectItem projectItem = AddFileToProject("template.tt"); + EnableCustomToolRunForProject(); + ConfigureCustomToolFileNamesForProject("template.tt"); + CreateBeforeBuildCustomToolProjectItems(); + + List projectItems = GetProjectItems(); + + FileProjectItem[] expectedProjectItems = new FileProjectItem[] { + projectItem + }; + CollectionAssert.AreEqual(expectedProjectItems, projectItems); + } + + [Test] + public void GetProjectItems_BuildSingleProjectWithOneFileMatchingCustomToolFileNamesConfigured_NoProjectItemsReturnedWhenRunCustomToolIsDisabledForProject() + { + CreateProject(@"d:\MyProject\MyProject.csproj"); + AddFileToProject("template.tt"); + DisableCustomToolRunForProject(); + ConfigureCustomToolFileNamesForProject("template.tt"); + CreateBeforeBuildCustomToolProjectItems(); + + List projectItems = GetProjectItems(); + + Assert.AreEqual(0, projectItems.Count); + } + + [Test] + public void GetProjectItems_BuildSingleProjectWithOneFileMatchingCustomToolRunConfiguration_OtherNonMatchingProjectItemsNotReturned() + { + CreateProject(@"d:\MyProject\MyProject.csproj"); + FileProjectItem projectItem = AddFileToProject("template.t4"); + AddFileToProject("test.cs"); + EnableCustomToolRunForProject(); + ConfigureCustomToolFileNamesForProject("template.t4"); + CreateBeforeBuildCustomToolProjectItems(); + + List projectItems = GetProjectItems(); + + FileProjectItem[] expectedProjectItems = new FileProjectItem[] { + projectItem + }; + CollectionAssert.AreEqual(expectedProjectItems, projectItems); + } + + [Test] + public void GetProjectItems_BuildSingleProjectWithOneFileMatchingCustomToolRunConfiguration_ProjectItemInSubdirectoryReturned() + { + CreateProject(@"d:\MyProject\MyProject.csproj"); + FileProjectItem projectItem = AddFileToProject(@"Model\template.tt"); + EnableCustomToolRunForProject(); + ConfigureCustomToolFileNamesForProject("template.tt"); + CreateBeforeBuildCustomToolProjectItems(); + + List projectItems = GetProjectItems(); + + FileProjectItem[] expectedProjectItems = new FileProjectItem[] { + projectItem + }; + CollectionAssert.AreEqual(expectedProjectItems, projectItems); + } + + [Test] + public void GetProjectItems_BuildSingleProjectWithOneFileMatchingCustomToolRunConfiguration_ProjectItemReturnedWhenFileNameCaseIsDifferent() + { + CreateProject(@"d:\MyProject\MyProject.csproj"); + FileProjectItem projectItem = AddFileToProject("template.tt"); + EnableCustomToolRunForProject(); + ConfigureCustomToolFileNamesForProject("TEMPLATE.TT"); + CreateBeforeBuildCustomToolProjectItems(); + + List projectItems = GetProjectItems(); + + FileProjectItem[] expectedProjectItems = new FileProjectItem[] { + projectItem + }; + CollectionAssert.AreEqual(expectedProjectItems, projectItems); + } + + [Test] + public void GetProjectItems_SolutionContainingOneProjectWithMatchingCustomToolFileName_ReturnsOneProjectItem() + { + IProject project = CreateProject(@"d:\MyProject\MyProject.csproj"); + FileProjectItem projectItem = AddFileToProject("template.tt"); + EnableCustomToolRunForProject(); + ConfigureCustomToolFileNamesForProject("TEMPLATE.TT"); + CreateSolution(project); + CreateBeforeBuildCustomToolProjectItemsUsingSolution(); + + List projectItems = GetProjectItems(); + + FileProjectItem[] expectedProjectItems = new FileProjectItem[] { + projectItem + }; + CollectionAssert.AreEqual(expectedProjectItems, projectItems); + } + + [Test] + public void GetProjectItems_SolutionWithNoProjects_ReturnsNoProjectItems() + { + CreateSolution(); + CreateBeforeBuildCustomToolProjectItemsUsingSolution(); + + List projectItems = GetProjectItems(); + + Assert.AreEqual(0, projectItems.Count); + } + + [Test] + public void GetProjectItems_SolutionContainingTwoProjectsWithMatchingCustomToolFileNameInSecondProject_ReturnsOneProjectItem() + { + IProject project1 = CreateProject(@"d:\MyProject\FirstProject.csproj"); + IProject project2 = CreateProject(@"d:\MyProject\SecondProject.csproj"); + FileProjectItem projectItem = AddFileToProject("template.tt"); + EnableCustomToolRunForProject(); + ConfigureCustomToolFileNamesForProject("TEMPLATE.TT"); + CreateSolution(project1, project2); + CreateBeforeBuildCustomToolProjectItemsUsingSolution(); + + List projectItems = GetProjectItems(); + + FileProjectItem[] expectedProjectItems = new FileProjectItem[] { + projectItem + }; + CollectionAssert.AreEqual(expectedProjectItems, projectItems); + } + + [Test] + public void GetProjectItems_SolutionContainingTwoProjectsWithMatchingCustomToolFileNameInFirstProject_ReturnsOneProjectItem() + { + IProject project1 = CreateProject(@"d:\MyProject\FirstProject.csproj"); + FileProjectItem projectItem = AddFileToProject("template.tt"); + EnableCustomToolRunForProject(); + ConfigureCustomToolFileNamesForProject("TEMPLATE.TT"); + IProject project2 = CreateProject(@"d:\MyProject\SecondProject.csproj"); + CreateSolution(project1, project2); + CreateBeforeBuildCustomToolProjectItemsUsingSolution(); + + List projectItems = GetProjectItems(); + + FileProjectItem[] expectedProjectItems = new FileProjectItem[] { + projectItem + }; + CollectionAssert.AreEqual(expectedProjectItems, projectItems); + } + + [Test] + public void GetProjectItems_SolutionContainingTwoProjectsBothWithFilesAndMatchingCustomToolFileNameInFirstProject_ReturnsOneProjectItem() + { + IProject project1 = CreateProject(@"d:\MyProject\FirstProject.csproj"); + FileProjectItem projectItem = AddFileToProject("template.tt"); + EnableCustomToolRunForProject(); + ConfigureCustomToolFileNamesForProject("TEMPLATE.TT"); + IProject project2 = CreateProject(@"d:\MyProject\SecondProject.csproj"); + AddFileToProject("test.cs"); + CreateSolution(project1, project2); + CreateBeforeBuildCustomToolProjectItemsUsingSolution(); + + List projectItems = GetProjectItems(); + + FileProjectItem[] expectedProjectItems = new FileProjectItem[] { + projectItem + }; + CollectionAssert.AreEqual(expectedProjectItems, projectItems); + } + } +} diff --git a/src/Main/Base/Test/Project/ProjectCustomToolOptionsTests.cs b/src/Main/Base/Test/Project/ProjectCustomToolOptionsTests.cs new file mode 100644 index 0000000000..39981dc3f2 --- /dev/null +++ b/src/Main/Base/Test/Project/ProjectCustomToolOptionsTests.cs @@ -0,0 +1,212 @@ +// 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.Collections.Generic; +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Project; +using NUnit.Framework; +using Rhino.Mocks; + +namespace ICSharpCode.SharpDevelop.Tests.Project +{ + [TestFixture] + public class ProjectCustomToolOptionsTests + { + IProject project; + Properties projectSpecificProperties; + ProjectCustomToolOptions projectCustomToolOptions; + Properties properties; + + void CreateProject() + { + projectSpecificProperties = new Properties(); + project = MockRepository.GenerateStub(); + project.Stub(p => p.ProjectSpecificProperties).Return(projectSpecificProperties); + } + + void CreateProjectWithExistingCustomToolProperties(string fileNames) + { + CreateProjectWithExistingCustomToolProperties(false, fileNames); + } + + void CreateProjectWithExistingCustomToolProperties(bool runOnBuild, string fileNames = "") + { + CreateProject(); + properties = new Properties(); + properties.Set("runOnBuild", runOnBuild); + properties.Set("fileNames", fileNames); + projectSpecificProperties.Set("customTool", properties); + } + + void CreateProjectCustomToolsOptions() + { + projectCustomToolOptions = new ProjectCustomToolOptions(project); + } + + [Test] + public void RunCustomToolOnBuild_ProjectHasNoExistingProjectCustomToolProperties_ReturnsFalse() + { + CreateProject(); + CreateProjectCustomToolsOptions(); + + bool run = projectCustomToolOptions.RunCustomToolOnBuild; + + Assert.IsFalse(run); + } + + [Test] + public void FileNames_ProjectHasNoExistingProjectCustomToolProperties_ReturnsEmptyString() + { + CreateProject(); + CreateProjectCustomToolsOptions(); + + string fileNames = projectCustomToolOptions.FileNames; + + Assert.AreEqual(String.Empty, fileNames); + } + + [Test] + public void RunCustomToolOnBuild_ProjectPropertyRunCustomToolOnBuildIsTrue_ReturnsTrue() + { + CreateProjectWithExistingCustomToolProperties(runOnBuild: true); + CreateProjectCustomToolsOptions(); + + bool run = projectCustomToolOptions.RunCustomToolOnBuild; + + Assert.IsTrue(run); + } + + [Test] + public void FileNames_ProjectPropertyFileNamesIsNotEmptyString_ReturnsFileName() + { + CreateProjectWithExistingCustomToolProperties(fileNames: "T4MVC.tt"); + CreateProjectCustomToolsOptions(); + + string fileNames = projectCustomToolOptions.FileNames; + + Assert.AreEqual("T4MVC.tt", fileNames); + } + + [Test] + public void RunCustomToolOnBuild_ChangeRunCustomToolOnBuildToTrue_StoredInProjectProperties() + { + CreateProjectWithExistingCustomToolProperties(runOnBuild: false); + CreateProjectCustomToolsOptions(); + + projectCustomToolOptions.RunCustomToolOnBuild = true; + + CreateProjectCustomToolsOptions(); + bool run = projectCustomToolOptions.RunCustomToolOnBuild; + Assert.IsTrue(run); + } + + [Test] + public void RunCustomToolOnBuild_ChangeRunCustomToolOnBuildToFalse_StoredInProjectProperties() + { + CreateProjectWithExistingCustomToolProperties(runOnBuild: true); + CreateProjectCustomToolsOptions(); + + projectCustomToolOptions.RunCustomToolOnBuild = false; + + CreateProjectCustomToolsOptions(); + bool run = projectCustomToolOptions.RunCustomToolOnBuild; + Assert.IsFalse(run); + } + + [Test] + public void FileNames_ChangeFileNamesFromEmptyStringToFileName_StoredInProjectProperties() + { + CreateProjectWithExistingCustomToolProperties(fileNames: String.Empty); + CreateProjectCustomToolsOptions(); + + projectCustomToolOptions.FileNames = "abc.tt"; + + CreateProjectCustomToolsOptions(); + string fileNames = projectCustomToolOptions.FileNames; + Assert.AreEqual("abc.tt", fileNames); + } + + [Test] + public void SplitFileNames_FileNamesIsSemiColonSeparatedOfTwoFiles_ReturnsTwoFiles() + { + CreateProjectWithExistingCustomToolProperties("a.t4;b.t4"); + CreateProjectCustomToolsOptions(); + + IList fileNames = projectCustomToolOptions.SplitFileNames(); + + string[] expectedFileNames = new string[] { + "a.t4", + "b.t4" + }; + CollectionAssert.AreEqual(expectedFileNames, fileNames); + } + + [Test] + public void SplitFileNames_FileNamesIsCommaSeparatedOfTwoFiles_ReturnsTwoFiles() + { + CreateProjectWithExistingCustomToolProperties("a.t4,b.t4"); + CreateProjectCustomToolsOptions(); + + IList fileNames = projectCustomToolOptions.SplitFileNames(); + + string[] expectedFileNames = new string[] { + "a.t4", + "b.t4" + }; + CollectionAssert.AreEqual(expectedFileNames, fileNames); + } + + [Test] + public void SplitFileNames_FileNamesIsSemiColonSeparatedOfTwoFilesWithWhitespace_ReturnsTwoFilesWithWhitespaceRemoved() + { + CreateProjectWithExistingCustomToolProperties(" a.t4 ; b.t4 "); + CreateProjectCustomToolsOptions(); + + IList fileNames = projectCustomToolOptions.SplitFileNames(); + + string[] expectedFileNames = new string[] { + "a.t4", + "b.t4" + }; + CollectionAssert.AreEqual(expectedFileNames, fileNames); + } + + [Test] + public void SplitFileNames_FileNamesIsTwoFilesEachOnSeparateLine_ReturnsTwoFiles() + { + string text = + "a.t4\r\n" + + "b.t4"; + CreateProjectWithExistingCustomToolProperties(text); + CreateProjectCustomToolsOptions(); + + IList fileNames = projectCustomToolOptions.SplitFileNames(); + + string[] expectedFileNames = new string[] { + "a.t4", + "b.t4" + }; + CollectionAssert.AreEqual(expectedFileNames, fileNames); + } + + [Test] + public void SplitFileNames_FileNamesIsTwoFilesEachOnSeparateLineWithEmptyLineBetweenThemAndOneAtEnd_ReturnsTwoFiles() + { + string text = + "a.t4\r\n" + + "\r\n" + + "b.t4\r\n"; + CreateProjectWithExistingCustomToolProperties(text); + CreateProjectCustomToolsOptions(); + + IList fileNames = projectCustomToolOptions.SplitFileNames(); + + string[] expectedFileNames = new string[] { + "a.t4", + "b.t4" + }; + CollectionAssert.AreEqual(expectedFileNames, fileNames); + } + } +} diff --git a/src/Main/Base/Test/Utils/ProjectHelper.cs b/src/Main/Base/Test/Utils/ProjectHelper.cs new file mode 100644 index 0000000000..459362f89c --- /dev/null +++ b/src/Main/Base/Test/Utils/ProjectHelper.cs @@ -0,0 +1,37 @@ +// 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.Collections.Generic; +using System.Collections.ObjectModel; +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Project; +using Rhino.Mocks; + +namespace ICSharpCode.SharpDevelop.Tests.Utils +{ + public class ProjectHelper + { + public IProject Project = MockRepository.GenerateMock(); + public List ProjectItems = new List(); + public Properties ProjectSpecificProperties = new Properties(); + + public ProjectHelper(string fileName) + { + Project.Stub(p => p.FileName).Return(fileName); + + Project + .Stub(p => p.Items) + .Return(null) + .WhenCalled(mi => mi.ReturnValue = new ReadOnlyCollection(ProjectItems)); + + Project.Stub(p => p.ProjectSpecificProperties).Return(ProjectSpecificProperties); + Project.Stub(p => p.SyncRoot).Return(new Object()); + } + + public void AddProjectItem(ProjectItem projectItem) + { + ProjectItems.Add(projectItem); + } + } +}