Forge
csharpdeeb25a2
1#nullable enable
2
3using CascadeIDE.Services.Intercom;
4using Xunit;
5
6namespace CascadeIDE.Tests;
7
8public sealed class IntercomMemberFileInferenceTests
9{
10 [Fact]
11 public void TryResolveRelativeFile_UniqueMemberInSidecar_InfersFile()
12 {
13 var dir = createWorkspace();
14 seedMember(dir, "src/A.cs", "Foo.Bar", 10, 20);
15 seedMember(dir, "src/B.cs", "Other.Baz", 1, 5);
16
17 Assert.True(
18 IntercomMemberFileInference.TryResolveRelativeFile(
19 explicitRelativeFile: null,
20 memberKey: "Foo.Bar",
21 activeFilePath: null,
22 workspaceRoot: dir,
23 solutionPath: null,
24 indexDirectoryRelative: null,
25 out var file,
26 out var error),
27 error);
28
29 Assert.Equal("src/A.cs", file);
30 }
31
32 [Fact]
33 public void TryResolveRelativeFile_AmbiguousMember_ReturnsError()
34 {
35 var dir = createWorkspace();
36 seedMember(dir, "src/A.cs", "Run", 10, 20);
37 seedMember(dir, "src/B.cs", "Run", 30, 40);
38
39 Assert.False(
40 IntercomMemberFileInference.TryResolveRelativeFile(
41 null,
42 "Run",
43 activeFilePath: null,
44 workspaceRoot: dir,
45 solutionPath: null,
46 indexDirectoryRelative: null,
47 out _,
48 out var error));
49
50 Assert.Contains("нескольких файлах", error);
51 }
52
53 [Fact]
54 public void TryResolveRelativeFile_ActiveFilePreferredWhenAlsoInIndex()
55 {
56 var dir = createWorkspace();
57 seedMember(dir, "src/A.cs", "Run", 10, 20);
58 seedMember(dir, "src/B.cs", "Run", 30, 40);
59 var active = Path.Combine(dir, "src", "B.cs");
60
61 Assert.True(
62 IntercomMemberFileInference.TryResolveRelativeFile(
63 null,
64 "Run",
65 active,
66 dir,
67 solutionPath: null,
68 indexDirectoryRelative: null,
69 out var file,
70 out var error),
71 error);
72
73 Assert.Equal("src/B.cs", file);
74 }
75
76 [Fact]
77 public void IntercomCodeRefParser_BareMember_ResolvesFileFromSidecar()
78 {
79 var dir = createWorkspace();
80 seedMember(dir, "src/A.cs", "Foo.Bar", 10, 20);
81
82 var editor = IntercomAttachmentResolveAtSend.EditorSnapshot.ForMcpBracketResolve(null);
83 Assert.True(
84 IntercomCodeRefParser.TryParse(
85 "M:Foo.Bar",
86 editor,
87 dir,
88 solutionPath: null,
89 out var query,
90 out var error,
91 indexDirectoryRelative: null),
92 error);
93
94 Assert.Equal("src/A.cs", query.File.Replace('\\', '/'));
95 Assert.Equal("Foo.Bar", query.MemberKey);
96 }
97
98 private static void seedMember(string workspace, string relativePath, string memberKey, int lineStart, int lineEnd)
99 {
100 var cache = IntercomAttachResolveCacheContext.From(workspace, null, relativePath);
101 var absolute = Path.Combine(workspace, relativePath.Replace('/', Path.DirectorySeparatorChar));
102 Directory.CreateDirectory(Path.GetDirectoryName(absolute)!);
103 if (!File.Exists(absolute))
104 File.WriteAllText(absolute, "// stub\n");
105
106 var mtime = File.GetLastWriteTimeUtc(absolute).Ticks;
107 IntercomSymbolLineIndex.ReplaceFileSymbols(
108 cache,
109 relativePath,
110 mtime,
111 [new IntercomSymbolLineEntry("docid", memberKey, lineStart, lineEnd)]);
112 }
113
114 private static string createWorkspace()
115 {
116 var dir = Path.Combine(Path.GetTempPath(), nameof(IntercomMemberFileInferenceTests) + "_" + Guid.NewGuid().ToString("N"));
117 Directory.CreateDirectory(dir);
118 return dir;
119 }
120}
121
View only · write via MCP/CIDE