Skip to content

Commit d9edf76

Browse files
authored
feat(namespace): update fully qualified type references (#39)
1 parent bd0ebfd commit d9edf76

File tree

4 files changed

+118
-2
lines changed

4 files changed

+118
-2
lines changed

src/CodingWithCalvin.ProjectRenamifier/Commands/RenamifyProjectCommand.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,12 @@ private void RenameProject(Project project, DTE2 dte)
161161
SourceFileService.UpdateUsingStatementsInSolution(dte.Solution, currentName, newName);
162162
});
163163

164+
// Step 11: Update fully qualified type references across the solution
165+
ExecuteStep(progressDialog, stepIndex++, () =>
166+
{
167+
SourceFileService.UpdateFullyQualifiedReferencesInSolution(dte.Solution, currentName, newName);
168+
});
169+
164170
// Mark as complete and close after a brief delay
165171
progressDialog.Complete();
166172
DoEvents();

src/CodingWithCalvin.ProjectRenamifier/Dialogs/RenameProgressDialog.xaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
44
Title="Renaming Project"
55
Width="400"
6-
Height="340"
6+
Height="360"
77
ResizeMode="NoResize"
88
WindowStartupLocation="CenterOwner"
99
ShowInTaskbar="False">

src/CodingWithCalvin.ProjectRenamifier/Dialogs/RenameProgressDialog.xaml.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ public RenameProgressDialog(string projectName)
2626
new ProgressStep("Renaming project directory"),
2727
new ProgressStep("Updating project references"),
2828
new ProgressStep("Re-adding project to solution"),
29-
new ProgressStep("Updating using statements")
29+
new ProgressStep("Updating using statements"),
30+
new ProgressStep("Updating fully qualified references")
3031
};
3132

3233
StepsList.ItemsSource = Steps;

src/CodingWithCalvin.ProjectRenamifier/Services/SourceFileService.cs

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,115 @@ namespace CodingWithCalvin.ProjectRenamifier.Services
1010
/// </summary>
1111
internal static class SourceFileService
1212
{
13+
/// <summary>
14+
/// Updates fully qualified type references in all .cs files across the entire solution.
15+
/// For example: OldName.MyClass → NewName.MyClass
16+
/// </summary>
17+
/// <param name="solution">The solution to scan.</param>
18+
/// <param name="oldNamespace">The old namespace to find.</param>
19+
/// <param name="newNamespace">The new namespace to replace with.</param>
20+
/// <returns>The number of files modified.</returns>
21+
public static int UpdateFullyQualifiedReferencesInSolution(Solution solution, string oldNamespace, string newNamespace)
22+
{
23+
ThreadHelper.ThrowIfNotOnUIThread();
24+
25+
var modifiedCount = 0;
26+
27+
foreach (Project project in solution.Projects)
28+
{
29+
modifiedCount += UpdateFullyQualifiedReferencesInProjectTree(project, oldNamespace, newNamespace);
30+
}
31+
32+
return modifiedCount;
33+
}
34+
35+
/// <summary>
36+
/// Recursively updates fully qualified references in a project (handles solution folders).
37+
/// </summary>
38+
private static int UpdateFullyQualifiedReferencesInProjectTree(Project project, string oldNamespace, string newNamespace)
39+
{
40+
ThreadHelper.ThrowIfNotOnUIThread();
41+
42+
if (project == null)
43+
{
44+
return 0;
45+
}
46+
47+
// Handle solution folders
48+
if (project.Kind == EnvDTE.Constants.vsProjectKindSolutionItems)
49+
{
50+
var count = 0;
51+
foreach (ProjectItem item in project.ProjectItems)
52+
{
53+
if (item.SubProject != null)
54+
{
55+
count += UpdateFullyQualifiedReferencesInProjectTree(item.SubProject, oldNamespace, newNamespace);
56+
}
57+
}
58+
return count;
59+
}
60+
61+
// Process actual project
62+
if (!string.IsNullOrEmpty(project.FullName) && File.Exists(project.FullName))
63+
{
64+
var projectDirectory = Path.GetDirectoryName(project.FullName);
65+
if (!string.IsNullOrEmpty(projectDirectory) && Directory.Exists(projectDirectory))
66+
{
67+
return UpdateFullyQualifiedReferencesInDirectory(projectDirectory, oldNamespace, newNamespace);
68+
}
69+
}
70+
71+
return 0;
72+
}
73+
74+
/// <summary>
75+
/// Updates fully qualified references in all .cs files within a directory.
76+
/// </summary>
77+
private static int UpdateFullyQualifiedReferencesInDirectory(string directory, string oldNamespace, string newNamespace)
78+
{
79+
var csFiles = Directory.GetFiles(directory, "*.cs", SearchOption.AllDirectories);
80+
var modifiedCount = 0;
81+
82+
foreach (var filePath in csFiles)
83+
{
84+
if (UpdateFullyQualifiedReferencesInFile(filePath, oldNamespace, newNamespace))
85+
{
86+
modifiedCount++;
87+
}
88+
}
89+
90+
return modifiedCount;
91+
}
92+
93+
/// <summary>
94+
/// Updates fully qualified type references in a single source file.
95+
/// Matches patterns like OldName.MyClass, OldName.Sub.Type but not SomeOldName.Type
96+
/// </summary>
97+
/// <param name="filePath">Full path to the .cs file.</param>
98+
/// <param name="oldNamespace">The old namespace to find.</param>
99+
/// <param name="newNamespace">The new namespace to replace with.</param>
100+
/// <returns>True if the file was modified, false otherwise.</returns>
101+
public static bool UpdateFullyQualifiedReferencesInFile(string filePath, string oldNamespace, string newNamespace)
102+
{
103+
var encoding = DetectEncoding(filePath);
104+
var content = File.ReadAllText(filePath, encoding);
105+
var originalContent = content;
106+
107+
// Pattern matches OldName followed by a dot and an identifier
108+
// Uses word boundary \b to avoid matching partial names like SomeOldName
109+
// Matches: OldName.Class, OldName.Sub.Class, etc.
110+
var pattern = $@"\b{Regex.Escape(oldNamespace)}\.";
111+
content = Regex.Replace(content, pattern, $"{newNamespace}.");
112+
113+
if (content != originalContent)
114+
{
115+
File.WriteAllText(filePath, content, encoding);
116+
return true;
117+
}
118+
119+
return false;
120+
}
121+
13122
/// <summary>
14123
/// Updates using statements in all .cs files across the entire solution.
15124
/// </summary>

0 commit comments

Comments
 (0)