diff --git a/src/StringExtensions.cs b/src/StringExtensions.cs
index b4d5665..31b2480 100644
--- a/src/StringExtensions.cs
+++ b/src/StringExtensions.cs
@@ -11,6 +11,16 @@ namespace StringResourceVisualizer
{
public static class StringExtensions
{
+ ///
+ /// Whether a file name is that of a Visual Studio solution file: the .sln format or the newer, XML based, .slnx format.
+ ///
+ public static bool IsSolutionFileName(this string fileName)
+ {
+ return !string.IsNullOrEmpty(fileName)
+ && (fileName.EndsWith(".sln", StringComparison.InvariantCultureIgnoreCase)
+ || fileName.EndsWith(".slnx", StringComparison.InvariantCultureIgnoreCase));
+ }
+
public static async Task IndexOfAnyAsync(this string source, params string[] values)
{
try
diff --git a/src/StringResVizPackage.cs b/src/StringResVizPackage.cs
index 2f5100d..0ff024c 100644
--- a/src/StringResVizPackage.cs
+++ b/src/StringResVizPackage.cs
@@ -270,7 +270,7 @@ private async Task SetUpRunningDocumentTableEventsAsync(CancellationToken cancel
private void WatchForSolutionOrProjectChanges(string solutionFileName)
{
// It might actually be the project file name if no solution file exists
- if (solutionFileName.EndsWith(".sln", StringComparison.InvariantCultureIgnoreCase))
+ if (solutionFileName.IsSolutionFileName())
{
this.SlnWatcher.Filter = Path.GetFileName(solutionFileName);
this.SlnWatcher.Path = Path.GetDirectoryName(solutionFileName);
@@ -315,7 +315,7 @@ private async void SlnWatcher_Renamed(object sender, RenamedEventArgs e)
try
{
// Don't want to know about temporary files created during save.
- if (e.FullPath.EndsWith(".sln"))
+ if (e.FullPath.IsSolutionFileName())
{
await this.SetOrUpdateListOfResxFilesAsync(Path.GetDirectoryName(e.FullPath));
}
diff --git a/src/StringResourceVisualizer.Tests/StringExtensionsTests.cs b/src/StringResourceVisualizer.Tests/StringExtensionsTests.cs
new file mode 100644
index 0000000..466c279
--- /dev/null
+++ b/src/StringResourceVisualizer.Tests/StringExtensionsTests.cs
@@ -0,0 +1,73 @@
+//
+// Copyright (c) Matt Lacey. All rights reserved.
+//
+
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace StringResourceVisualizer.Tests
+{
+ [TestClass]
+ public class StringExtensionsTests
+ {
+ [TestMethod]
+ public void IsSolutionFileName_Sln()
+ {
+ TestIt(@"C:\Source\MyApp\MyApp.sln", true);
+ }
+
+ [TestMethod]
+ public void IsSolutionFileName_Slnx()
+ {
+ TestIt(@"C:\Source\MyApp\MyApp.slnx", true);
+ }
+
+ [TestMethod]
+ public void IsSolutionFileName_Sln_UpperCase()
+ {
+ TestIt(@"C:\Source\MyApp\MyApp.SLN", true);
+ }
+
+ [TestMethod]
+ public void IsSolutionFileName_Slnx_MixedCase()
+ {
+ TestIt(@"C:\Source\MyApp\MyApp.SlnX", true);
+ }
+
+ [TestMethod]
+ public void IsSolutionFileName_ProjectFile()
+ {
+ TestIt(@"C:\Source\MyApp\MyApp.csproj", false);
+ }
+
+ [TestMethod]
+ public void IsSolutionFileName_SolutionFilter()
+ {
+ TestIt(@"C:\Source\MyApp\MyApp.slnf", false);
+ }
+
+ [TestMethod]
+ public void IsSolutionFileName_ExtensionInTheMiddleOfThePath()
+ {
+ TestIt(@"C:\Source\MyApp.sln\readme.txt", false);
+ }
+
+ [TestMethod]
+ public void IsSolutionFileName_Empty()
+ {
+ TestIt(string.Empty, false);
+ }
+
+ [TestMethod]
+ public void IsSolutionFileName_Null()
+ {
+ TestIt(null, false);
+ }
+
+ private void TestIt(string input, bool expected)
+ {
+ var actual = input.IsSolutionFileName();
+
+ Assert.AreEqual(expected, actual);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/StringResourceVisualizer.Tests/StringResourceVisualizer.Tests.csproj b/src/StringResourceVisualizer.Tests/StringResourceVisualizer.Tests.csproj
index 82e550c..d77d350 100644
--- a/src/StringResourceVisualizer.Tests/StringResourceVisualizer.Tests.csproj
+++ b/src/StringResourceVisualizer.Tests/StringResourceVisualizer.Tests.csproj
@@ -44,6 +44,7 @@
+