Forge
csharpdeeb25a2
1using System.Text;
2using System.Xml.Linq;
3
4namespace CascadeIDE.Services;
5
6/// <summary>Reads <c>ImplicitUsings</c>, <c>Using Include/Remove</c> from a <c>.csproj</c>.</summary>
7public sealed record CSharpProjectUsingsProfile(
8 string ProjectPath,
9 string? SdkAttribute,
10 bool ImplicitUsingsEnabled,
11 IReadOnlyList<string> UsingIncludes,
12 IReadOnlyList<string> UsingRemoves)
13{
14 public static CSharpProjectUsingsProfile? TryLoad(string? projectPath)
15 {
16 if (string.IsNullOrWhiteSpace(projectPath) || !File.Exists(projectPath))
17 return null;
18
19 try
20 {
21 var doc = XDocument.Load(projectPath);
22 var root = doc.Root;
23 if (root is null)
24 return null;
25
26 var sdk = root.Attribute("Sdk")?.Value;
27 var implicitUsings = ReadImplicitUsings(root);
28 var includes = ReadUsingItems(root, "Include");
29 var removes = ReadUsingItems(root, "Remove");
30 return new CSharpProjectUsingsProfile(
31 projectPath,
32 sdk,
33 implicitUsings,
34 includes,
35 removes);
36 }
37 catch
38 {
39 return null;
40 }
41 }
42
43 public IReadOnlyList<string> ResolveNamespaces()
44 {
45 var set = new HashSet<string>(StringComparer.Ordinal);
46 foreach (var ns in CSharpSdkImplicitUsingsCatalog.ForProjectSdk(SdkAttribute, ImplicitUsingsEnabled))
47 set.Add(ns);
48 foreach (var ns in UsingIncludes)
49 set.Add(ns);
50 foreach (var ns in UsingRemoves)
51 set.Remove(ns);
52 return set.OrderBy(static n => n, StringComparer.Ordinal).ToList();
53 }
54
55 private static bool ReadImplicitUsings(XElement root)
56 {
57 var value = ReadProperty(root, "ImplicitUsings");
58 if (string.IsNullOrWhiteSpace(value))
59 return SdkPresent(root);
60 return value.Equals("enable", StringComparison.OrdinalIgnoreCase)
61 || value.Equals("true", StringComparison.OrdinalIgnoreCase);
62 }
63
64 private static bool SdkPresent(XElement root) =>
65 !string.IsNullOrWhiteSpace(root.Attribute("Sdk")?.Value);
66
67 private static string? ReadProperty(XElement root, string name)
68 {
69 foreach (var pg in root.Elements("PropertyGroup"))
70 {
71 var el = pg.Element(name);
72 if (el is not null)
73 return el.Value.Trim();
74 }
75
76 return null;
77 }
78
79 private static List<string> ReadUsingItems(XElement root, string attributeName)
80 {
81 var list = new List<string>();
82 foreach (var item in root.Elements("ItemGroup").SelectMany(g => g.Elements("Using")))
83 {
84 var value = item.Attribute(attributeName)?.Value?.Trim();
85 if (!string.IsNullOrWhiteSpace(value))
86 list.Add(value);
87 }
88
89 return list;
90 }
91}
92
View only · write via MCP/CIDE