| 1 | using CascadeIDE.Features.WorkspaceNavigation.Application; |
| 2 | using Xunit; |
| 3 | |
| 4 | namespace CascadeIDE.Tests; |
| 5 | |
| 6 | public sealed class WorkspaceNavigationMapControlFlowCursorTests |
| 7 | { |
| 8 | [Fact] |
| 9 | public void ResolveControlFlowCursorForRefresh_uses_editor_caret_when_anchor_is_current_file() |
| 10 | { |
| 11 | const string source = """ |
| 12 | class Demo |
| 13 | { |
| 14 | void A() |
| 15 | { |
| 16 | B(); |
| 17 | } |
| 18 | |
| 19 | void B() { } |
| 20 | } |
| 21 | """; |
| 22 | var offset = source.IndexOf("B();", StringComparison.Ordinal); |
| 23 | var (line, column) = WorkspaceNavigationMapOrchestrator.ResolveControlFlowCursorForRefresh( |
| 24 | navigationPath: @"D:\w\Demo.cs", |
| 25 | currentPath: @"D:\w\Demo.cs", |
| 26 | sourceText: source, |
| 27 | caretOrSelectionOffset: offset); |
| 28 | |
| 29 | Assert.True(line > 1); |
| 30 | Assert.True(column > 1); |
| 31 | } |
| 32 | |
| 33 | [Fact] |
| 34 | public void ResolveControlFlowCursorForRefresh_prefers_graph_navigate_line_over_caret() |
| 35 | { |
| 36 | const string source = """ |
| 37 | class Demo |
| 38 | { |
| 39 | void A() |
| 40 | { |
| 41 | B(); |
| 42 | } |
| 43 | |
| 44 | void B() { } |
| 45 | } |
| 46 | """; |
| 47 | var caretInA = source.IndexOf("void A", StringComparison.Ordinal); |
| 48 | const int lineInB = 9; |
| 49 | var (line, column) = WorkspaceNavigationMapOrchestrator.ResolveControlFlowCursorForRefresh( |
| 50 | navigationPath: @"D:\w\Demo.cs", |
| 51 | currentPath: @"D:\w\Demo.cs", |
| 52 | sourceText: source, |
| 53 | caretOrSelectionOffset: caretInA, |
| 54 | navigateToLine: lineInB, |
| 55 | navigateToColumn: 1); |
| 56 | |
| 57 | Assert.Equal(lineInB, line); |
| 58 | Assert.Equal(1, column); |
| 59 | } |
| 60 | |
| 61 | [Fact] |
| 62 | public void TryOffsetForLine_maps_one_based_line_to_offset() |
| 63 | { |
| 64 | const string source = "a\nbb\nccc"; |
| 65 | Assert.Equal(0, WorkspaceNavigationMapOrchestrator.TryOffsetForLine(source, 1)); |
| 66 | Assert.Equal(2, WorkspaceNavigationMapOrchestrator.TryOffsetForLine(source, 2)); |
| 67 | Assert.Equal(5, WorkspaceNavigationMapOrchestrator.TryOffsetForLine(source, 3)); |
| 68 | } |
| 69 | |
| 70 | [Fact] |
| 71 | public void ResolveControlFlowCursorForRefresh_returns_null_when_navigation_path_not_current_editor() |
| 72 | { |
| 73 | const string source = """ |
| 74 | class Demo |
| 75 | { |
| 76 | void Entry() { Run(); } |
| 77 | void Run() { } |
| 78 | } |
| 79 | """; |
| 80 | var (line, column) = WorkspaceNavigationMapOrchestrator.ResolveControlFlowCursorForRefresh( |
| 81 | navigationPath: @"D:\w\Program.cs", |
| 82 | currentPath: @"D:\w\Other.cs", |
| 83 | sourceText: source, |
| 84 | caretOrSelectionOffset: 999); |
| 85 | |
| 86 | Assert.Null(line); |
| 87 | Assert.Null(column); |
| 88 | } |
| 89 | } |
| 90 | |