diff --git a/src/CodingWithCalvin.ProjectRenamifier/CodingWithCalvin.ProjectRenamifier.csproj b/src/CodingWithCalvin.ProjectRenamifier/CodingWithCalvin.ProjectRenamifier.csproj
index 7f04dd2..e85f232 100644
--- a/src/CodingWithCalvin.ProjectRenamifier/CodingWithCalvin.ProjectRenamifier.csproj
+++ b/src/CodingWithCalvin.ProjectRenamifier/CodingWithCalvin.ProjectRenamifier.csproj
@@ -71,6 +71,7 @@
+
True
True
diff --git a/src/CodingWithCalvin.ProjectRenamifier/Commands/RenamifyProjectCommand.cs b/src/CodingWithCalvin.ProjectRenamifier/Commands/RenamifyProjectCommand.cs
index fd5ef3f..e0ed85e 100644
--- a/src/CodingWithCalvin.ProjectRenamifier/Commands/RenamifyProjectCommand.cs
+++ b/src/CodingWithCalvin.ProjectRenamifier/Commands/RenamifyProjectCommand.cs
@@ -83,9 +83,11 @@ private void RenameProject(Project project, DTE2 dte)
// Update RootNamespace and AssemblyName in .csproj
ProjectFileService.UpdateProjectFile(projectFilePath, currentName, newName);
+ // Update namespace declarations in source files
+ SourceFileService.UpdateNamespacesInProject(projectFilePath, currentName, newName);
+
// TODO: Implement remaining rename operations
// See open issues for requirements:
- // - #8: Update namespace declarations in source files
// - #9: Update using statements across solution
// - #11: Solution folder support
// - #12: Progress indication
diff --git a/src/CodingWithCalvin.ProjectRenamifier/Services/SourceFileService.cs b/src/CodingWithCalvin.ProjectRenamifier/Services/SourceFileService.cs
new file mode 100644
index 0000000..b03173d
--- /dev/null
+++ b/src/CodingWithCalvin.ProjectRenamifier/Services/SourceFileService.cs
@@ -0,0 +1,108 @@
+using System.IO;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace CodingWithCalvin.ProjectRenamifier.Services
+{
+ ///
+ /// Service for updating namespace declarations in source files.
+ ///
+ internal static class SourceFileService
+ {
+ ///
+ /// Updates namespace declarations in all .cs files within the project directory.
+ ///
+ /// Full path to the .csproj file.
+ /// The old namespace to find.
+ /// The new namespace to replace with.
+ /// The number of files modified.
+ public static int UpdateNamespacesInProject(string projectFilePath, string oldNamespace, string newNamespace)
+ {
+ var projectDirectory = Path.GetDirectoryName(projectFilePath);
+ if (string.IsNullOrEmpty(projectDirectory))
+ {
+ return 0;
+ }
+
+ var csFiles = Directory.GetFiles(projectDirectory, "*.cs", SearchOption.AllDirectories);
+ var modifiedCount = 0;
+
+ foreach (var filePath in csFiles)
+ {
+ if (UpdateNamespacesInFile(filePath, oldNamespace, newNamespace))
+ {
+ modifiedCount++;
+ }
+ }
+
+ return modifiedCount;
+ }
+
+ ///
+ /// Updates namespace declarations in a single source file.
+ ///
+ /// Full path to the .cs file.
+ /// The old namespace to find.
+ /// The new namespace to replace with.
+ /// True if the file was modified, false otherwise.
+ public static bool UpdateNamespacesInFile(string filePath, string oldNamespace, string newNamespace)
+ {
+ // Detect file encoding
+ var encoding = DetectEncoding(filePath);
+ var content = File.ReadAllText(filePath, encoding);
+ var originalContent = content;
+
+ // Pattern for block-scoped namespace: namespace OldName { or namespace OldName\n{
+ // Also handles nested: namespace OldName.Something
+ var blockPattern = $@"(\bnamespace\s+){Regex.Escape(oldNamespace)}(\s*[\{{\r\n]|\.|\s*$)";
+ content = Regex.Replace(content, blockPattern, $"$1{newNamespace}$2");
+
+ // Pattern for file-scoped namespace: namespace OldName;
+ // Also handles nested: namespace OldName.Something;
+ var fileScopedPattern = $@"(\bnamespace\s+){Regex.Escape(oldNamespace)}(\.[\w.]*)?(\s*;)";
+ content = Regex.Replace(content, fileScopedPattern, $"$1{newNamespace}$2$3");
+
+ if (content != originalContent)
+ {
+ File.WriteAllText(filePath, content, encoding);
+ return true;
+ }
+
+ return false;
+ }
+
+ ///
+ /// Detects the encoding of a file, defaulting to UTF-8 if not determinable.
+ ///
+ private static Encoding DetectEncoding(string filePath)
+ {
+ // Read the BOM to detect encoding
+ var bom = new byte[4];
+ using (var file = new FileStream(filePath, FileMode.Open, FileAccess.Read))
+ {
+ file.Read(bom, 0, 4);
+ }
+
+ // Detect encoding from BOM
+ if (bom[0] == 0xef && bom[1] == 0xbb && bom[2] == 0xbf)
+ {
+ return Encoding.UTF8;
+ }
+ if (bom[0] == 0xff && bom[1] == 0xfe && bom[2] == 0 && bom[3] == 0)
+ {
+ return Encoding.UTF32;
+ }
+ if (bom[0] == 0xff && bom[1] == 0xfe)
+ {
+ return Encoding.Unicode; // UTF-16 LE
+ }
+ if (bom[0] == 0xfe && bom[1] == 0xff)
+ {
+ return Encoding.BigEndianUnicode; // UTF-16 BE
+ }
+
+ // Default to UTF-8 without BOM
+ return new UTF8Encoding(false);
+ }
+ }
+}