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

feat: Add .xml to file types that can be updated by ListingManager #75

Merged
merged 10 commits into from
Oct 12, 2023
19 changes: 19 additions & 0 deletions ListingManager.Tests/ListingInformationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,24 @@ public void Constructor_GivenValidListings_PropertiesPopulatedSuccessfully(strin

Assert.AreEqual(description ?? "", listingInformation.ListingDescription);
}

[TestMethod]
[DataRow("Listing01.01.cs")]
[DataRow("Listing05.04.Something.xml")]
[DataRow("Listing05.04.Something.XML")]
public void Constructor_GivenValidListingFileTypes_CreatesNewListingInformation(string listing)
{
ListingInformation listingInformation = new(listing);
Assert.IsNotNull(listingInformation);
Assert.AreEqual(System.IO.Path.GetExtension(listing), listingInformation.ListingExtension);
}

[TestMethod]
[DataRow("Listing01.02.something.txt")]
[DataRow("Listing01.02A.csproj")]
public void Constructor_GivenInvalidListingFileTypes_ThrowsArgumentException(string listing)
{
Assert.ThrowsException<System.ArgumentException>(() => new ListingInformation(listing));
}
}
}
83 changes: 63 additions & 20 deletions ListingManager.Tests/ListingManagerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public void GetAllExtraListings_ExtraListingsReturned()
@"Listing02.03C.cs"
};

var tempDir = CreateTempDirectory(name: "Chapter02");
DirectoryInfo tempDir = CreateTempDirectory(name: "Chapter02");
ICollection<string> expectedFiles = filesToMake;
expectedFiles.Remove(@"Listing02.02.cs");
expectedFiles = ConvertFileNamesToFullPath(expectedFiles, tempDir).ToList();
Expand Down Expand Up @@ -94,7 +94,7 @@ public void UpdateChapterListingNumbers_ListingsWithinListMissing_ListingsRenumb

ListingManager.UpdateChapterListingNumbers(TempDirectory.FullName, singleDir: true);

var files = Directory.EnumerateFiles(TempDirectory.FullName)
List<string> files = Directory.EnumerateFiles(TempDirectory.FullName)
.Where(x => Path.GetExtension(x) == ".cs").OrderBy(x => x).ToList();
CollectionAssert.AreEquivalent(expectedFiles, files);
}
Expand Down Expand Up @@ -130,7 +130,7 @@ public void UpdateChapterListingNumbers_ListingAtBeginningOfListMissing_Listings

ListingManager.UpdateChapterListingNumbers(TempDirectory.FullName, singleDir: true);

var files = Directory.EnumerateFiles(TempDirectory.FullName)
List<string> files = Directory.EnumerateFiles(TempDirectory.FullName)
.Where(x => Path.GetExtension(x) == ".cs").OrderBy(x => x).ToList();

CollectionAssert.AreEquivalent((ICollection)expectedFiles, files);
Expand Down Expand Up @@ -195,7 +195,7 @@ public void UpdateChapterListingNumbers_MultipleListingsMissing_ListingsRenumber

ListingManager.UpdateChapterListingNumbers(TempDirectory.FullName, singleDir: true);

var files = Directory.EnumerateFiles(TempDirectory.FullName)
List<string> files = Directory.EnumerateFiles(TempDirectory.FullName)
.Where(x => Path.GetExtension(x) == ".cs").OrderBy(x => x).ToList();

CollectionAssert.AreEquivalent((ICollection)expectedFiles, files);
Expand Down Expand Up @@ -238,7 +238,7 @@ public void UpdateChapterListingNumbers_AdditionalListings_ListingsRenumbered()

ListingManager.UpdateChapterListingNumbers(TempDirectory.FullName, singleDir: true);

var files = Directory.EnumerateFiles(TempDirectory.FullName)
List<string> files = Directory.EnumerateFiles(TempDirectory.FullName)
.Where(x => Path.GetExtension(x) == ".cs").OrderBy(x => x).ToList();

CollectionAssert.AreEquivalent((ICollection)expectedFiles, files);
Expand Down Expand Up @@ -284,15 +284,15 @@ public void UpdateChapterListingNumbers_UnitTestsAlsoUpdated_ListingsAndTestsUpd
" public class Program { }",
"}"
};
var tempDir = CreateTempDirectory();
var chapterDir = CreateTempDirectory(tempDir, name: "Chapter01");
DirectoryInfo tempDir = CreateTempDirectory();
DirectoryInfo chapterDir = CreateTempDirectory(tempDir, name: "Chapter01");
CreateTempDirectory(tempDir, name: "Chapter01.Tests");
WriteFiles(tempDir, filesToMake, toWrite);
expectedFiles = ConvertFileNamesToFullPath(expectedFiles, tempDir).ToList();

ListingManager.UpdateChapterListingNumbers(chapterDir.FullName);

var files = FileManager.GetAllFilesAtPath(tempDir.FullName, true)
List<string> files = FileManager.GetAllFilesAtPath(tempDir.FullName, true)
.Where(x => Path.GetExtension(x) == ".cs").OrderBy(x => x).ToList();

CollectionAssert.AreEquivalent((ICollection)expectedFiles, files);
Expand Down Expand Up @@ -340,18 +340,18 @@ public void
" public class Program { }",
"}"
};
var tempDir = CreateTempDirectory();
var chapterDir = CreateTempDirectory(tempDir, name: "Chapter42");
DirectoryInfo tempDir = CreateTempDirectory();
DirectoryInfo chapterDir = CreateTempDirectory(tempDir, name: "Chapter42");
CreateTempDirectory(tempDir, name: "Chapter42.Tests");
WriteFiles(tempDir, filesToMake, toWrite);
expectedFiles = ConvertFileNamesToFullPath(expectedFiles, tempDir).ToList();

ListingManager.UpdateChapterListingNumbers(chapterDir.FullName, byFolder: true);

var files = FileManager.GetAllFilesAtPath(tempDir.FullName, true)
List<string> files = FileManager.GetAllFilesAtPath(tempDir.FullName, true)
.Where(x => Path.GetExtension(x) == ".cs").OrderBy(x => x).ToList();

//Assert
// Assert
CollectionAssert.AreEquivalent((ICollection)expectedFiles, files);
}

Expand Down Expand Up @@ -458,18 +458,18 @@ public void
" public class Program { }",
"}"
};
var tempDir = CreateTempDirectory();
var chapterDir = CreateTempDirectory(tempDir, name: "Chapter01");
DirectoryInfo tempDir = CreateTempDirectory();
DirectoryInfo chapterDir = CreateTempDirectory(tempDir, name: "Chapter01");
CreateTempDirectory(tempDir, name: "Chapter01.Tests");
WriteFiles(tempDir, filesToMake, toWrite);
expectedFiles = ConvertFileNamesToFullPath(expectedFiles, tempDir).ToList();

ListingManager.UpdateChapterListingNumbers(chapterDir.FullName, byFolder: true);

var files = FileManager.GetAllFilesAtPath(tempDir.FullName, true)
List<string> files = FileManager.GetAllFilesAtPath(tempDir.FullName, true)
.Where(x => Path.GetExtension(x) == ".cs").OrderBy(x => x).ToList();

//Assert
// Assert
CollectionAssert.AreEquivalent((ICollection)expectedFiles, files);
}

Expand Down Expand Up @@ -516,22 +516,65 @@ public void
"}"
};

var tempDir = CreateTempDirectory();
var chapterDir = CreateTempDirectory(tempDir, name: "Chapter42");
DirectoryInfo tempDir = CreateTempDirectory();
DirectoryInfo chapterDir = CreateTempDirectory(tempDir, name: "Chapter42");
CreateTempDirectory(tempDir, name: "Chapter42.Tests");
WriteFiles(tempDir, filesToMake, toWrite);
expectedFiles = ConvertFileNamesToFullPath(expectedFiles, tempDir).ToList();

ListingManager.UpdateChapterListingNumbers(chapterDir.FullName,
byFolder: true, chapterOnly: true);

var files = FileManager.GetAllFilesAtPath(tempDir.FullName, true)
List<string> files = FileManager.GetAllFilesAtPath(tempDir.FullName, true)
.Where(x => Path.GetExtension(x) == ".cs").OrderBy(x => x).ToList();

//Assert
// Assert
CollectionAssert.AreEquivalent((ICollection)expectedFiles, files);
}

[TestMethod]
public void RenumberAllFilesIncludingXML_DontChangeFiles_ListingsAndTestsUpdated()
{
// Make sure csproj file is created, but doesn't get renumbered (is ignored)
List<string> filesToMake = new()
{
@"Chapter18.csproj",
@"Chapter18\Listing18.01.UsingTypeGetPropertiesToObtainAnObjectsPublicProperties.cs",
@"Chapter18\Listing18.02.UsingTypeofToCreateASystem.TypeInstance.cs",
@"Chapter18\Listing18.03.csproj.xml",
@"Chapter18\Listing18.04.DeclaringTheStackClass.cs",
@"Chapter18\Listing18.05.ReflectionWithGenerics.cs",
@"Chapter18.Tests\Listing18.01.UsingTypeGetPropertiesToObtainAnObjectsPublicProperties.Tests.cs",
@"Chapter18.Tests\Listing18.02.Tests.cs",
@"Chapter18.Tests\Listing18.05.ReflectionWithGenerics.Tests.cs",
};
List<string> expectedFiles = filesToMake.GetRange(1, filesToMake.Count - 1);
Assert.AreEqual(filesToMake.Count - 1, expectedFiles.Count);

IEnumerable<string> toWrite = new List<string>
{
"namespace AddisonWesley.Michaelis.EssentialCSharp.Chapter18.Listing18_01",
"{",
" using System;",
" using System.Reflection;",
" public class Program { }",
"}"
};

DirectoryInfo tempDir = CreateTempDirectory();
DirectoryInfo chapterDir = CreateTempDirectory(tempDir, name: "Chapter18");
CreateTempDirectory(tempDir, name: "Chapter18.Tests");
WriteFiles(tempDir, filesToMake, toWrite);
expectedFiles = ConvertFileNamesToFullPath(expectedFiles, tempDir).ToList();

ListingManager.UpdateChapterListingNumbers(chapterDir.FullName);

List<string> files = FileManager.GetAllFilesAtPath(tempDir.FullName, true)
.Where(x => ListingInformation.ApprovedFileTypes.Contains(Path.GetExtension(x))).OrderBy(x => x).ToList();

// Assert
CollectionAssert.AreEquivalent(expectedFiles, files, $"Files are in dir: {tempDir}");
}

[TestMethod]
[DataRow("Chapter01", "Listing01.01A.cs")]
Expand Down
17 changes: 14 additions & 3 deletions ListingManager/ListingInformation.cs
Original file line number Diff line number Diff line change
@@ -1,24 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace ListingManager
{
public class ListingInformation
public partial class ListingInformation
{
public static IReadOnlyList<string> ApprovedFileTypes { get; } = new[] { ".cs", ".xml" };
public const string TemporaryExtension = ".tmp";
public int ChapterNumber { get; }
public int ListingNumber { get; }
public string ListingSuffix { get; }
public string ListingDescription { get; }
public string TemporaryPath { get; }
public string Path => TemporaryPath.Remove(TemporaryPath.Length - TemporaryExtension.Length, TemporaryExtension.Length);
public string ListingExtension { get; }

public ListingInformation(string listingPath)
{
Regex regex = new(@"Listing(\d{2}).(\d{2})([A-Za-z]*)(\.{1}(.*))?.cs$");
Regex regex = ExtractListingNameFromAnyApprovedFileTypes();

var matches = regex.Match(listingPath);

if (ApprovedFileTypes.Contains(matches.Groups[6].Value.ToLower()) is false) throw new ArgumentException("Listing path is not of an approved file type.", nameof(listingPath));

if (int.TryParse(matches.Groups[1].Value, out int chapterNumber)
&& int.TryParse(matches.Groups[2].Value, out int listingNumber)
&& matches.Success)
Expand All @@ -28,11 +34,16 @@ public ListingInformation(string listingPath)
ListingSuffix = !string.IsNullOrWhiteSpace(matches.Groups[3].Value) ? matches.Groups[3].Value : "";
ListingDescription = !string.IsNullOrWhiteSpace(matches.Groups[5].Value) ? matches.Groups[5].Value : "";
TemporaryPath = listingPath + TemporaryExtension;
ListingExtension = matches.Groups[6].Value;
}
else
{
throw new ArgumentException("Listing information not successfully able to be parsed from listing path.", nameof(listingPath));
}
}
}

// Match any approved files regex: regexr.com/7lfi2
[GeneratedRegex("Listing(\\d{2}).(\\d{2})([A-Za-z]*)(\\.{1}(.*))*(\\.(\\w+))$")]
private static partial Regex ExtractListingNameFromAnyApprovedFileTypes();
}
}
44 changes: 13 additions & 31 deletions ListingManager/ListingManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@

private static bool TryGetListing(string listingPath, out ListingInformation? listingData)
{
listingData = null;
listingData = null;

if (!ListingInformation.ApprovedFileTypes.Contains(Path.GetExtension(listingPath))) return false;

if (Path.GetExtension(listingPath) != ".cs") return false;

try
{
Expand All @@ -40,8 +41,8 @@
}

return true;
}

}
/// <summary>
/// Updates the namespace, file names, and corresponding test file of the target listing. This has a cascading
/// effect, resulting in the renaming of subsequent listings in the same chapter.
Expand All @@ -55,12 +56,12 @@
public static void UpdateChapterListingNumbers(string pathToChapter,
bool verbose = false, bool preview = false, bool byFolder = false, bool chapterOnly = false, bool singleDir = false)
{
var listingData = new List<ListingInformation?>();
List<ListingInformation?> listingData = new();
List<string> allListings = FileManager.GetAllFilesAtPath(pathToChapter)
.OrderBy(x => x)
.Where(x =>
{
bool result = TryGetListing(x, out var data);
bool result = TryGetListing(x, out ListingInformation? data);
if (result) listingData.Add(data);
return result;
}).ToList();
Expand All @@ -73,7 +74,7 @@
.OrderBy(x => x)
.Where(x => Path.GetExtension(x) == ListingInformation.TemporaryExtension).ToList();

var testListingData = new List<ListingInformation?>();
List<ListingInformation?> testListingData = new();

List<string> allTestListings = Array.Empty<string>().ToList();
if (!singleDir)
Expand Down Expand Up @@ -109,10 +110,10 @@

if (curListingData is null || !chapterOnly && !byFolder && listingNumber == curListingData.ListingNumber)
{
File.Copy(curListingData?.TemporaryPath, curListingData?.Path, true);

Check warning on line 113 in ListingManager/ListingManager.cs

View workflow job for this annotation

GitHub Actions / build-and-test on windows-latest

Possible null reference argument for parameter 'sourceFileName' in 'void File.Copy(string sourceFileName, string destFileName, bool overwrite)'.

Check warning on line 113 in ListingManager/ListingManager.cs

View workflow job for this annotation

GitHub Actions / build-and-test on windows-latest

Possible null reference argument for parameter 'destFileName' in 'void File.Copy(string sourceFileName, string destFileName, bool overwrite)'.

Check warning on line 113 in ListingManager/ListingManager.cs

View workflow job for this annotation

GitHub Actions / build-and-test on windows-latest

Possible null reference argument for parameter 'sourceFileName' in 'void File.Copy(string sourceFileName, string destFileName, bool overwrite)'.

Check warning on line 113 in ListingManager/ListingManager.cs

View workflow job for this annotation

GitHub Actions / build-and-test on windows-latest

Possible null reference argument for parameter 'destFileName' in 'void File.Copy(string sourceFileName, string destFileName, bool overwrite)'.
if (testListingData.FirstOrDefault(x => x?.ListingNumber == curListingData.ListingNumber && x.ListingSuffix == curListingData.ListingSuffix) is ListingInformation currentTestListingData)
{
File.Copy(currentTestListingData?.TemporaryPath, currentTestListingData?.Path, true);

Check warning on line 116 in ListingManager/ListingManager.cs

View workflow job for this annotation

GitHub Actions / build-and-test on windows-latest

Possible null reference argument for parameter 'sourceFileName' in 'void File.Copy(string sourceFileName, string destFileName, bool overwrite)'.

Check warning on line 116 in ListingManager/ListingManager.cs

View workflow job for this annotation

GitHub Actions / build-and-test on windows-latest

Possible null reference argument for parameter 'destFileName' in 'void File.Copy(string sourceFileName, string destFileName, bool overwrite)'.

Check warning on line 116 in ListingManager/ListingManager.cs

View workflow job for this annotation

GitHub Actions / build-and-test on windows-latest

Possible null reference argument for parameter 'sourceFileName' in 'void File.Copy(string sourceFileName, string destFileName, bool overwrite)'.

Check warning on line 116 in ListingManager/ListingManager.cs

View workflow job for this annotation

GitHub Actions / build-and-test on windows-latest

Possible null reference argument for parameter 'destFileName' in 'void File.Copy(string sourceFileName, string destFileName, bool overwrite)'.
}
continue;
} //default
Expand All @@ -132,7 +133,7 @@

UpdateListingNamespace(cur, listingChapterNumber,
completeListingNumber,
curListingData.ListingDescription, verbose, preview);
curListingData, verbose, preview);

if (testListingData.Where(x => x?.ListingNumber == curListingData.ListingNumber && x.ListingSuffix == curListingData.ListingSuffix).FirstOrDefault() is ListingInformation curTestListingData)
{
Expand Down Expand Up @@ -224,7 +225,7 @@
/// <param name="verbose">When true, enables verbose console output</param>
/// <param name="preview">When true, leaves files in place and only print console output</param>
private static void UpdateListingNamespace(string path, int chapterNumber, string listingNumber,
string listingData, bool verbose = false, bool preview = false)
ListingInformation listingData, bool verbose = false, bool preview = false)
{
string paddedChapterNumber = chapterNumber.ToString("00");

Expand All @@ -240,15 +241,15 @@
paddedListingNumber = listingNumber.PadLeft(2, '0'); //default
}

string newFileNameTemplate = "Listing{0}.{1}{2}.cs";
string newFileNameTemplate = "Listing{0}.{1}{2}" + listingData.ListingExtension;
string newNamespace = "AddisonWesley.Michaelis.EssentialCSharp" +
$".Chapter{paddedChapterNumber}" +
$".Listing{paddedChapterNumber}_" +
paddedListingNumber;
string newFileName = string.Format(newFileNameTemplate,
paddedChapterNumber,
paddedListingNumber,
string.IsNullOrWhiteSpace(listingData) ? "" : $".{listingData}");
string.IsNullOrWhiteSpace(listingData.ListingDescription) ? "" : $".{listingData.ListingDescription}");

if (verbose)
{
Expand Down Expand Up @@ -322,32 +323,13 @@
return false;
}

private static readonly string TestHeaderLayout =
@"using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace AddisonWesley.Michaelis.EssentialCSharp.Chapter{0}.Listing{0}_{1}.Tests";

private static readonly string TestBodyLayout =
@"
{
[TestClass]
public class ProgramTests
{
[TestMethod]
public void UnitTest1()
{
Assert.Fail();
}
}
}";

public static string ExecuteBashCommand(string command)
{
// according to: https://stackoverflow.com/a/15262019/637142
// thanks to this we will pass everything as one command
command = command.Replace("\"", "\"\"");

string fileName = System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
string fileName = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
? "CMD.exe"
: "/bin/bash";

Expand Down
4 changes: 1 addition & 3 deletions ListingManager/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ public class Program
_| |_| | | | || __/ | | | | | __/ (__| |_
|_____|_| |_|\__\___|_|_|_| |_|\___|\___|\__|";

private const string InteractivePromptPrefix = "INTL {0} ({1})>";

public static void Main(string path = "", ListingModes mode = ListingModes.ListingUpdating,
bool verbose = false,
bool preview = false,
Expand Down Expand Up @@ -45,7 +43,7 @@ public static void Main(string path = "", ListingModes mode = ListingModes.Listi
{
case ListingModes.ListingUpdating:
Console.WriteLine($"Updating listing namespaces of: {path}");
ListingManager.UpdateChapterListingNumbers(path, verbose, preview, byFolder, chapterOnly);
ListingManager.UpdateChapterListingNumbers(path, verbose, preview, byFolder, chapterOnly, false);
break;
case ListingModes.ScanForMismatchedListings:
var extraListings = ListingManager.GetAllExtraListings(path).OrderBy(x => x);
Expand Down
Loading