Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added RegexMatchGroups task #278

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ Test
*.nupkg
*.msi
*.chm
.vs
/Tools
/build.txt
5 changes: 5 additions & 0 deletions Documentation/Overview.html
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,11 @@ <h3>Current Community Tasks</h3>
<td>Task to filter an Input list with a Regex expression. Output list contains
items from Input list that matched given expression</td>
</tr>
<tr>
<td>RegexMatchGroups</td>
<td>Task to filter an Input list and to match groups with a Regex expression. Output list contains
matched group values together with corresponding group names and original values from Input list that matched given expression</td>
</tr>
<tr>
<td>RegexReplace</td>
<td>Task to replace portions of strings within the Input list Output list
Expand Down
30 changes: 30 additions & 0 deletions Documentation/TaskDocs.md
Original file line number Diff line number Diff line change
Expand Up @@ -2310,6 +2310,36 @@ Matches from TestGroup those names ending in a, b or c



## <a id="RegexMatchGroups">RegexMatchGroups</a>
### Description
Task to filter an Input list and to match groups with a Regex expression.
Output list contains matched group values together with corresponding group names and original values from Input list that matched given expression
### Example
Matches TestGroup items containing at lease two numeric groups connected by a dot and returns the first two groups with values

<ItemGroup>
<TestGroup Include="foo.my.foo.foo.test.o" />
<TestGroup Include="foo.my.faa.foo.test.a" />
<TestGroup Include="foo.my.fbb.foo.test.b" />
<TestGroup Include="foo.my.fcc.foo.test.c" />
<TestGroup Include="foo.my.fdd.foo.test.d" />
<TestGroup Include="foo.my.fee.foo.test.e" />
<TestGroup Include="foo.my.fff.foo.test.f" />
<TestGroup Include="1.2" />
<TestGroup Include="1.2.3" />
</ItemGroup>
<Target Name="Test">
<!-- Outputs only items that consist of at least twho numbers conected by a dot (1.2|1.2.3) as groups (1 from 1.2, 2 from 1.2, 1 from 1.2.3, 2 from 1.2.3)-->
<RegexMatch Input="@(TestGroup)" Expression="(?<FirstGroup>\d+)\.(?<SecondGroup>\d+)">
<Output ItemName ="MatchReturn" TaskParameter="Output" />
</RegexMatch>
<Message Text="&#xA;Output Match:&#xA;@(MatchReturn->' matched value: %(Identity), original value: %(OriginalItem), matched group name: %(GroupName)', '&#xA;')" />
</Target>


* * *


## <a id="RegexReplace">RegexReplace</a>
### Description
Task to replace portions of strings within the Input list
Expand Down
230 changes: 137 additions & 93 deletions Source/MSBuild.Community.Tasks.Tests/Regex/RegexTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,103 +2,147 @@

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

namespace MSBuild.Community.Tasks.Tests
{
/// <summary>
/// Tests for RegexMatch and RegexReplace functions
/// </summary>
[TestFixture]
public class RegexTest
{
/// <summary>
/// Tests RegExMatch finds correct number of matches in a known sample set
/// </summary>
[Test(Description = "RegexMatch test")]
public void RegexMatchExecute()
{
RegexMatch task = new RegexMatch();
task.BuildEngine = new MockBuild();

task.Input = TaskUtility.StringArrayToItemArray("foo.my.foo.foo.test.o", "foo.my.faa.foo.test.a", "foo.my.fbb.foo.test.b", "foo.my.fcc.foo.test.c", "foo.my.fdd.foo.test.d");
task.Expression = new TaskItem("[a-c]$");

Assert.IsTrue(task.Execute(), "Execute Failed");

Assert.AreEqual(3, task.Output.Length, "Match should have matched three items");

}

/// <summary>
/// Tests RegexReplace by removing the first "foo." string from a list of items
/// </summary>
[Test(Description = "RegexReplace test, removes first 'foo.' from a list of test items")]
public void RegexReplaceRemoveFirstFoo()
{
RegexReplace task = new RegexReplace();
task.BuildEngine = new MockBuild();

task.Input = TaskUtility.StringArrayToItemArray("foo.my.foo.foo.test.o", "foo.my.faa.foo.test.a", "foo.my.fbb.foo.test.b", "foo.my.fcc.foo.test.c", "foo.my.fdd.foo.test.d");
task.Expression = new TaskItem("foo\\.");
task.Count = new TaskItem("1");

Assert.IsTrue(task.Execute(), "Execute Failed");

foreach (ITaskItem item in task.Output)
{
Assert.IsTrue(!item.ItemSpec.StartsWith("foo."), string.Format("Item still starts with foo: {0}", item.ItemSpec));
}
}

/// <summary>
/// Tests RegexReplace by replacing the string "foo." appearing after the 6th character with the string "oop." from a list of items
/// </summary>
[Test(Description = "Tests RegexReplace by replacing the string 'foo.' appearing after the 6th character with the string 'oop.' from a list of items")]
public void RegexReplaceFooForOop()
{
RegexReplace task = new RegexReplace();
task.BuildEngine = new MockBuild();
string[] expectedResult = new string[] { "foo.my.oop.oop.test.o", "foo.my.faa.oop.test.a", "foo.my.fbb.oop.test.b", "foo.my.fcc.oop.test.c", "foo.my.fdd.oop.test.d" };

task.Input = TaskUtility.StringArrayToItemArray("foo.my.foo.foo.test.o", "foo.my.faa.foo.test.a", "foo.my.fbb.foo.test.b", "foo.my.fcc.foo.test.c", "foo.my.fdd.foo.test.d");
task.Expression = new TaskItem("foo\\.");
task.StartAt = new TaskItem("6");
task.Replacement = new TaskItem("oop.");

Assert.IsTrue(task.Execute(), "Execute Failed");

for (int ndx = 0; ndx < task.Output.Length; ndx++)
{
Assert.AreEqual(expectedResult[ndx], task.Output[ndx].ItemSpec, "Results did not match expectations");
}
}


/// <summary>
/// Tests RegexReplace by replacing the first "." with a "!" starting from the right from a list of items
/// </summary>
[Test(Description = "Tests RegexReplace by replacing the first '.' with a '!' starting from the right from a list of items")]
public void RegexReplaceLastDotForBang()
{
RegexReplace task = new RegexReplace();
task.BuildEngine = new MockBuild();

task.Input = TaskUtility.StringArrayToItemArray("foo.my.foo.foo.test.o", "foo.my.faa.foo.test.a", "foo.my.fbb.foo.test.b", "foo.my.fcc.foo.test.c", "foo.my.fdd.foo.test.d");
task.Expression = new TaskItem("\\.");
task.Replacement = new TaskItem("!");
task.Count = new TaskItem("1");
task.Options = TaskUtility.StringArrayToItemArray("RightToLeft");

Assert.IsTrue(task.Execute(), "Execute Failed");

foreach (ITaskItem item in task.Output)
{
Assert.AreEqual("!", item.ItemSpec.Substring(19, 1), string.Format("Item not replaced properly: {0}", item.ItemSpec));
}
}
}
}
/// <summary>
/// Tests for RegexMatch and RegexReplace functions
/// </summary>
[TestFixture]
public class RegexTest
{
/// <summary>
/// Tests RegExMatch finds correct number of matches in a known sample set
/// </summary>
[Test(Description = "RegexMatch test")]
public void RegexMatchExecute()
{
RegexMatch task = new RegexMatch();
task.BuildEngine = new MockBuild();

task.Input = TaskUtility.StringArrayToItemArray("foo.my.foo.foo.test.o", "foo.my.faa.foo.test.a", "foo.my.fbb.foo.test.b", "foo.my.fcc.foo.test.c", "foo.my.fdd.foo.test.d");
task.Expression = new TaskItem("[a-c]$");

Assert.IsTrue(task.Execute(), "Execute Failed");

Assert.AreEqual(3, task.Output.Length, "Match should have matched three items");

}

/// <summary>
/// Tests RegexReplace by removing the first "foo." string from a list of items
/// </summary>
[Test(Description = "RegexReplace test, removes first 'foo.' from a list of test items")]
public void RegexReplaceRemoveFirstFoo()
{
RegexReplace task = new RegexReplace();
task.BuildEngine = new MockBuild();

task.Input = TaskUtility.StringArrayToItemArray("foo.my.foo.foo.test.o", "foo.my.faa.foo.test.a", "foo.my.fbb.foo.test.b", "foo.my.fcc.foo.test.c", "foo.my.fdd.foo.test.d");
task.Expression = new TaskItem("foo\\.");
task.Count = new TaskItem("1");

Assert.IsTrue(task.Execute(), "Execute Failed");

foreach (ITaskItem item in task.Output)
{
Assert.IsTrue(!item.ItemSpec.StartsWith("foo."), string.Format("Item still starts with foo: {0}", item.ItemSpec));
}
}

/// <summary>
/// Tests RegexReplace by replacing the string "foo." appearing after the 6th character with the string "oop." from a list of items
/// </summary>
[Test(Description = "Tests RegexReplace by replacing the string 'foo.' appearing after the 6th character with the string 'oop.' from a list of items")]
public void RegexReplaceFooForOop()
{
RegexReplace task = new RegexReplace();
task.BuildEngine = new MockBuild();
string[] expectedResult = new string[] { "foo.my.oop.oop.test.o", "foo.my.faa.oop.test.a", "foo.my.fbb.oop.test.b", "foo.my.fcc.oop.test.c", "foo.my.fdd.oop.test.d" };

task.Input = TaskUtility.StringArrayToItemArray("foo.my.foo.foo.test.o", "foo.my.faa.foo.test.a", "foo.my.fbb.foo.test.b", "foo.my.fcc.foo.test.c", "foo.my.fdd.foo.test.d");
task.Expression = new TaskItem("foo\\.");
task.StartAt = new TaskItem("6");
task.Replacement = new TaskItem("oop.");

Assert.IsTrue(task.Execute(), "Execute Failed");

for (int ndx = 0; ndx < task.Output.Length; ndx++)
{
Assert.AreEqual(expectedResult[ndx], task.Output[ndx].ItemSpec, "Results did not match expectations");
}
}


/// <summary>
/// Tests RegexReplace by replacing the first "." with a "!" starting from the right from a list of items
/// </summary>
[Test(Description = "Tests RegexReplace by replacing the first '.' with a '!' starting from the right from a list of items")]
public void RegexReplaceLastDotForBang()
{
RegexReplace task = new RegexReplace();
task.BuildEngine = new MockBuild();

task.Input = TaskUtility.StringArrayToItemArray("foo.my.foo.foo.test.o", "foo.my.faa.foo.test.a", "foo.my.fbb.foo.test.b", "foo.my.fcc.foo.test.c", "foo.my.fdd.foo.test.d");
task.Expression = new TaskItem("\\.");
task.Replacement = new TaskItem("!");
task.Count = new TaskItem("1");
task.Options = TaskUtility.StringArrayToItemArray("RightToLeft");

Assert.IsTrue(task.Execute(), "Execute Failed");

foreach (ITaskItem item in task.Output)
{
Assert.AreEqual("!", item.ItemSpec.Substring(19, 1), string.Format("Item not replaced properly: {0}", item.ItemSpec));
}
}

/// <summary>
/// Tests RegexMatchGroups by extracting first and/or second numeric parts from numeric expressions concantenated by a dot
/// </summary>
[Test(Description = "Tests RegexMatchGroups by extracting first and/or second numeric parts from numeric expressions concantenated by a dot")]
public void RegexExtractValuesForDefinedGroup()
{
var task = new RegexMatchGroups
{
BuildEngine = new MockBuild(),
Expression = new TaskItem(@"(?<FirstGroup>\d+)\.(?<SecondGroup>\d+)"),
Input = TaskUtility.StringArrayToItemArray("1.2", "erster.zweiter", "1.2.3")
};

Assert.IsTrue(task.Execute(), "Execute Failed");

Assert.IsNotNull(
task.Output.FirstOrDefault(q =>
q.GetMetadata("OriginalItem").Equals("1.2") && q.GetMetadata("GroupName").Equals("FirstGroup") &&
q.ItemSpec.Equals("1"))
);

task = new RegexMatchGroups
{
BuildEngine = new MockBuild(),
Expression = new TaskItem(@"(?<FirstGroup>\d+)\.(?<SecondGroup>\d+)"),
Input = TaskUtility.StringArrayToItemArray("1","1.2.3")
};

Assert.IsTrue(task.Execute(), "Execute Failed");

Assert.IsNull(
task.Output.FirstOrDefault(q =>
q.GetMetadata("OriginalItem").Equals("1") && q.GetMetadata("GroupName").Equals("FirstGroup") &&
q.ItemSpec.Equals("1"))
);

Assert.IsNotNull(
task.Output.FirstOrDefault(q =>
q.GetMetadata("OriginalItem").Equals("1.2.3") && q.GetMetadata("GroupName").Equals("FirstGroup") &&
q.ItemSpec.Equals("1"))
);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
<UsingTask AssemblyFile="$(MSBuildCommunityTasksLib)" TaskName="MSBuild.Community.Tasks.RegistryRead" />
<UsingTask AssemblyFile="$(MSBuildCommunityTasksLib)" TaskName="MSBuild.Community.Tasks.RegistryWrite" />
<UsingTask AssemblyFile="$(MSBuildCommunityTasksLib)" TaskName="MSBuild.Community.Tasks.RegexMatch" />
<UsingTask AssemblyFile="$(MSBuildCommunityTasksLib)" TaskName="MSBuild.Community.Tasks.RegexMatchGroups" />
<UsingTask AssemblyFile="$(MSBuildCommunityTasksLib)" TaskName="MSBuild.Community.Tasks.RegexReplace" />
<UsingTask AssemblyFile="$(MSBuildCommunityTasksLib)" TaskName="MSBuild.Community.Tasks.RegexCompiler" />
<UsingTask AssemblyFile="$(MSBuildCommunityTasksLib)" TaskName="MSBuild.Community.Tasks.RoboCopy" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@
<Compile Include="NUnit3.cs" />
<Compile Include="PathUtil.cs" />
<Compile Include="Regex\RegexCompiler.cs" />
<Compile Include="Regex\RegexMatchGroups.cs" />
<Compile Include="Sandcastle\BuildAssembler.cs">
<SubType>Code</SubType>
</Compile>
Expand Down
Loading