-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSourceFileService.cs
More file actions
108 lines (96 loc) · 4.1 KB
/
SourceFileService.cs
File metadata and controls
108 lines (96 loc) · 4.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
namespace CodingWithCalvin.ProjectRenamifier.Services
{
/// <summary>
/// Service for updating namespace declarations in source files.
/// </summary>
internal static class SourceFileService
{
/// <summary>
/// Updates namespace declarations in all .cs files within the project directory.
/// </summary>
/// <param name="projectFilePath">Full path to the .csproj file.</param>
/// <param name="oldNamespace">The old namespace to find.</param>
/// <param name="newNamespace">The new namespace to replace with.</param>
/// <returns>The number of files modified.</returns>
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;
}
/// <summary>
/// Updates namespace declarations in a single source file.
/// </summary>
/// <param name="filePath">Full path to the .cs file.</param>
/// <param name="oldNamespace">The old namespace to find.</param>
/// <param name="newNamespace">The new namespace to replace with.</param>
/// <returns>True if the file was modified, false otherwise.</returns>
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;
}
/// <summary>
/// Detects the encoding of a file, defaulting to UTF-8 if not determinable.
/// </summary>
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);
}
}
}