Forge
csharp4405de34
1#nullable enable
2
3using CascadeIDE.Features.HybridIndex.Application;
4
5namespace CascadeIDE.Services.Intercom;
6
7/// <summary>Обход .cs под workspace для symbol sidecar (ADR 0135).</summary>
8internal static class IntercomSymbolLineIndexScanner
9{
10 private static readonly string[] SkipDirNames =
11 [
12 ".git",
13 "bin",
14 "obj",
15 "node_modules",
16 ".hybrid-codebase-index",
17 ];
18
19 public static IEnumerable<string> EnumerateCsFiles(string workspaceRoot, string indexDirectoryRelative)
20 {
21 if (string.IsNullOrWhiteSpace(workspaceRoot) || !Directory.Exists(workspaceRoot))
22 yield break;
23
24 var indexMarker = HybridIndexIndexDirectoryRelative.ResolveOrDefault(indexDirectoryRelative)
25 .Replace('\\', '/');
26
27 IEnumerable<string> dirs;
28 try
29 {
30 dirs = Directory.EnumerateDirectories(workspaceRoot, "*", SearchOption.AllDirectories);
31 }
32 catch
33 {
34 yield break;
35 }
36
37 var skipRoots = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
38 foreach (var dir in dirs)
39 {
40 var name = Path.GetFileName(dir);
41 if (SkipDirNames.Contains(name, StringComparer.OrdinalIgnoreCase))
42 skipRoots.Add(dir);
43 }
44
45 IEnumerable<string> files;
46 try
47 {
48 files = Directory.EnumerateFiles(workspaceRoot, "*.cs", SearchOption.AllDirectories);
49 }
50 catch
51 {
52 yield break;
53 }
54
55 foreach (var file in files)
56 {
57 if (isUnderSkippedRoot(file, skipRoots))
58 continue;
59
60 var rel = Path.GetRelativePath(workspaceRoot, file).Replace('\\', '/');
61 if (rel.Contains(indexMarker, StringComparison.OrdinalIgnoreCase))
62 continue;
63
64 yield return file;
65 }
66 }
67
68 private static bool isUnderSkippedRoot(string filePath, HashSet<string> skipRoots)
69 {
70 foreach (var root in skipRoots)
71 {
72 if (filePath.StartsWith(root + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase)
73 || string.Equals(filePath, root, StringComparison.OrdinalIgnoreCase))
74 {
75 return true;
76 }
77 }
78
79 return false;
80 }
81}
82
View only · write via MCP/CIDE