Skip to content

Commit af23073

Browse files
authored
Merge pull request #163 from sboulema/feature/window_synchronization_#159
feat: Window synchronization #159
2 parents c6e94aa + 9cbfd72 commit af23073

21 files changed

Lines changed: 457 additions & 145 deletions

.github/workflows/workflow.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ on:
77
- 'feature/**'
88

99
env:
10-
version: '10.5.${{ github.run_number }}'
10+
version: '10.6.${{ github.run_number }}'
1111
dotnetVersion: '8'
1212
repoUrl: ${{ github.server_url }}/${{ github.repository }}
1313
vsixPath: src/CodeNav/bin/Release/net472/CodeNav.vsix

docs/links.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ Here is a list of links to helpful pages I needed when developing this extension
2525
- [CompositeExtension Sample](https://github.com/microsoft/VSExtensibility/tree/main/New_Extensibility_Model/Samples/CompositeExtension)
2626
- [The CheckBox control](https://wpf-tutorial.com/basic-controls/the-checkbox-control/)
2727
- [Sorting enum by a custom attribute](https://stackoverflow.com/questions/61091166/sorting-enum-by-a-custom-attribute)
28+
- [TextView methods](https://github.com/llvm-mirror/clang/blob/master/tools%2Fclang-format-vs%2FClangFormat%2FVsix.cs#L34)
29+
- [TextView methods 2](https://github.com/msomeone/PeasyMotion/blob/466eaad0f0e731928c645b10f5f43f3519631ea0/Shared/VsMethodExtensions.cs#L115)
30+
- [TextView methods 3](https://github.com/VsixCommunity/Community.VisualStudio.Toolkit/blob/8624a25f504d7fc0bab5fa3434ce95be2466f438/src/toolkit/Community.VisualStudio.Toolkit.Shared/Windows/WindowFrame.cs#L232)
31+
- [Get Path of the document from IWpfTextView for non cs files](https://stackoverflow.com/questions/48068134/get-path-of-the-document-from-iwpftextview-for-non-cs-files)
2832

2933
## VSExtensibility Issues
3034
- [#545 - Feature request: Text Editor: Collapse/Expand ranges](https://github.com/microsoft/VSExtensibility/issues/545)

src/CodeNav.OutOfProc/ExtensionEntrypoint.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
using CodeNav.OutOfProc.Helpers;
2-
using CodeNav.OutOfProc.Services;
1+
using CodeNav.OutOfProc.Services;
32
using Microsoft.Extensions.DependencyInjection;
43
using Microsoft.VisualStudio.Extensibility;
54

@@ -37,6 +36,7 @@ protected override void InitializeServices(IServiceCollection serviceCollection)
3736
// As of now, any instance that ingests VisualStudioExtensibility is required to be added as a scoped
3837
// service.
3938
serviceCollection.AddScoped<OutputWindowService>();
40-
serviceCollection.AddScoped<OutliningHelper>();
39+
serviceCollection.AddScoped<OutliningService>();
40+
serviceCollection.AddScoped<WindowFrameService>();
4141
}
4242
}

src/CodeNav.OutOfProc/Helpers/SortHelper.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using CodeNav.OutOfProc.Services;
55
using CodeNav.OutOfProc.ViewModels;
66
using Microsoft.VisualStudio.Extensibility;
7+
using Microsoft.VisualStudio.Extensibility.Editor;
78

89
namespace CodeNav.OutOfProc.Helpers;
910

@@ -41,7 +42,11 @@ public static async Task ChangeSort(
4142

4243
ApplySort(codeDocumentService.CodeDocumentViewModel, sortOrder);
4344

44-
await codeDocumentService.UpdateCodeDocumentViewModel(clientContext.Extensibility, textViewSnapshot, cancellationToken);
45+
await codeDocumentService.UpdateCodeDocumentViewModel(
46+
clientContext.Extensibility,
47+
textViewSnapshot.FilePath,
48+
textViewSnapshot.Document.Text.CopyToString(),
49+
cancellationToken);
4550
}
4651

4752
/// <summary>

src/CodeNav.OutOfProc/Languages/CSharp/Mappers/DocumentMapper.cs

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,30 +3,12 @@
33
using Microsoft.CodeAnalysis.CSharp;
44
using Microsoft.CodeAnalysis.CSharp.Syntax;
55
using Microsoft.VisualStudio.Extensibility;
6-
using Microsoft.VisualStudio.Extensibility.Editor;
76
using Microsoft.VisualStudio.ProjectSystem.Query;
87

98
namespace CodeNav.OutOfProc.Languages.CSharp.Mappers;
109

1110
public class DocumentMapper
1211
{
13-
/// <summary>
14-
/// Map text document to list of code items.
15-
/// </summary>
16-
/// <param name="documentSnapshot">Document snapshot with latest version of text</param>
17-
/// <param name="excludeFilePath">File path of the document snaphot, used to exclude the saved version of the text</param>
18-
/// <param name="codeDocumentViewModel">Current view model connected to the CodeNav tool window</param>
19-
/// <param name="extensibility">Visual Studio extensibility used to retrieve all solution files for compilation</param>
20-
/// <param name="cancellationToken">Cancellation token</param>
21-
/// <returns>List of code items</returns>
22-
public static async Task<List<CodeItem>> MapDocument(
23-
ITextDocumentSnapshot documentSnapshot,
24-
string? excludeFilePath,
25-
CodeDocumentViewModel codeDocumentViewModel,
26-
VisualStudioExtensibility extensibility,
27-
CancellationToken cancellationToken)
28-
=> await MapDocument(documentSnapshot.Text.CopyToString(), excludeFilePath, codeDocumentViewModel, extensibility, cancellationToken);
29-
3012
/// <summary>
3113
/// Map text document to list of code items.
3214
/// </summary>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace CodeNav.OutOfProc.Models;
2+
3+
public sealed class DocumentView
4+
{
5+
public string FilePath { get; set; } = string.Empty;
6+
7+
public string Text { get; set; } = string.Empty;
8+
9+
public bool IsDocumentFrame { get; set; }
10+
}

src/CodeNav.OutOfProc/Services/CodeDocumentService.cs

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@
55
using CodeNav.OutOfProc.Models;
66
using CodeNav.OutOfProc.ViewModels;
77
using Microsoft.VisualStudio.Extensibility;
8-
using Microsoft.VisualStudio.Extensibility.Editor;
98
using Microsoft.VisualStudio.Extensibility.UI;
109
using System.Windows;
1110

1211
namespace CodeNav.OutOfProc.Services;
1312

1413
public class CodeDocumentService(
1514
OutputWindowService logService,
16-
OutliningHelper outliningHelper)
15+
OutliningService outliningService,
16+
WindowFrameService windowFrameService)
1717
{
1818
/// <summary>
1919
/// DataContext for the tool window.
@@ -34,17 +34,19 @@ public class CodeDocumentService(
3434

3535
public OutputWindowService LogService => logService;
3636

37-
public OutliningHelper OutliningHelper => outliningHelper;
37+
public OutliningService OutliningService => outliningService;
3838

3939
public async Task<CodeDocumentViewModel> UpdateCodeDocumentViewModel(
4040
VisualStudioExtensibility? extensibility,
41-
ITextViewSnapshot? textView,
41+
string? filePath,
42+
string? text,
4243
CancellationToken cancellationToken)
4344
{
4445
try
4546
{
4647
if (extensibility == null ||
47-
textView == null)
48+
string.IsNullOrEmpty(filePath) ||
49+
string.IsNullOrEmpty(text))
4850
{
4951
return CodeDocumentViewModel;
5052
}
@@ -60,20 +62,20 @@ public async Task<CodeDocumentViewModel> UpdateCodeDocumentViewModel(
6062

6163
// Get the new list of code items
6264
var codeItems = await DocumentMapper.MapDocument(
63-
textView.Document,
64-
textView.FilePath,
65+
text,
66+
filePath,
6567
CodeDocumentViewModel,
6668
extensibility,
6769
cancellationToken);
6870

69-
await logService.WriteInfo(textView, $"Found '{codeItems.Count}' code items");
71+
await logService.WriteInfo(filePath, $"Found '{codeItems.Count}' code items");
7072

7173
// Getting the new code items is done, cancel creating a loading placeholder
7274
await loadingCancellationTokenSource.CancelAsync();
7375

7476
// Set properties on the CodeDocumentViewModel that are needed for other features
7577
CodeDocumentViewModel.CodeDocumentService = this;
76-
CodeDocumentViewModel.FilePath = textView.FilePath ?? string.Empty;
78+
CodeDocumentViewModel.FilePath = filePath ?? string.Empty;
7779

7880
if (!codeItems.Any())
7981
{
@@ -85,37 +87,39 @@ public async Task<CodeDocumentViewModel> UpdateCodeDocumentViewModel(
8587
// And update the DataContext for the tool window
8688
CodeDocumentViewModel.CodeItems = SortHelper.Sort(codeItems, CodeDocumentViewModel.SortOrder);
8789

88-
await logService.WriteInfo(textView, $"Sorted code items on '{CodeDocumentViewModel.SortOrder}'");
90+
await logService.WriteInfo(filePath, $"Sorted code items on '{CodeDocumentViewModel.SortOrder}'");
8991

9092
// Apply highlights
9193
HighlightHelper.UnHighlight(CodeDocumentViewModel);
9294

93-
await logService.WriteInfo(textView, $"Remove highlight from all code items");
95+
await logService.WriteInfo(filePath, $"Remove highlight from all code items");
9496

9597
// Apply current visibility settings to the document
9698
VisibilityHelper.SetCodeItemVisibility(CodeDocumentViewModel, CodeDocumentViewModel.CodeItems, CodeDocumentViewModel.FilterRules);
9799

98-
await logService.WriteInfo(textView, $"Set code item visibility");
100+
await logService.WriteInfo(filePath, $"Set code item visibility");
99101

100102
// Apply filter rules
101103
FilterRuleHelper.ApplyFilterRules(CodeDocumentViewModel, CodeDocumentViewModel.CodeItems, CodeDocumentViewModel.FilterRules);
102104

103-
await logService.WriteInfo(textView, $"Set code item filter rules");
105+
await logService.WriteInfo(filePath, $"Set code item filter rules");
104106

105107
// Apply history items
106108
HistoryHelper.ApplyHistoryIndicator(CodeDocumentViewModel);
107109

108-
await logService.WriteInfo(textView, $"Apply history indicators");
110+
await logService.WriteInfo(filePath, $"Apply history indicators");
109111

110112
// Apply bookmarks
111113
BookmarkHelper.ApplyBookmarkIndicator(CodeDocumentViewModel);
112114

113-
await logService.WriteInfo(textView, $"Apply bookmark indicators");
115+
await logService.WriteInfo(filePath, $"Apply bookmark indicators");
114116

115117
// Apply outlining
116-
await OutliningHelper.SubscribeToRegionEvents(CodeDocumentViewModel);
118+
await OutliningService.SubscribeToRegionEvents(CodeDocumentViewModel);
117119

118-
await logService.WriteInfo(textView, $"Apply outlining");
120+
await logService.WriteInfo(filePath, $"Apply outlining");
121+
122+
await windowFrameService.SubscribeToWindowFrameEvents();
119123

120124
return CodeDocumentViewModel;
121125
}

src/CodeNav.OutOfProc/Services/IOutOfProcService.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ public interface IOutOfProcService
88

99
Task SetCodeItemIsExpanded(int spanStart, int spanEnd, bool isExpanded);
1010

11+
Task ProcessActiveFrameChanged(string documentViewJsonString);
12+
1113
public static class Configuration
1214
{
1315
public const string ServiceName = "CodeNav.OutOfProcService";
Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,16 @@
1-
using CodeNav.OutOfProc.Helpers;
1+
using CodeNav.OutOfProc.Models;
22
using Microsoft.ServiceHub.Framework;
33
using Microsoft.VisualStudio.Extensibility;
44
using Microsoft.VisualStudio.Extensibility.Shell;
5+
using System.Text.Json;
56

67
namespace CodeNav.OutOfProc.Services;
78

89
[VisualStudioContribution]
9-
internal class OutOfProcService : IOutOfProcService, IBrokeredService
10+
internal class OutOfProcService(
11+
VisualStudioExtensibility extensibility,
12+
CodeDocumentService codeDocumentService) : IOutOfProcService, IBrokeredService
1013
{
11-
private readonly VisualStudioExtensibility _extensibility;
12-
private readonly CodeDocumentService _codeDocumentService;
13-
14-
public OutOfProcService(
15-
VisualStudioExtensibility extensibility,
16-
CodeDocumentService codeDocumentService)
17-
{
18-
_extensibility = extensibility;
19-
_codeDocumentService = codeDocumentService;
20-
}
21-
2214
public static BrokeredServiceConfiguration BrokeredServiceConfiguration
2315
=> new(IOutOfProcService.Configuration.ServiceName, IOutOfProcService.Configuration.ServiceVersion, typeof(OutOfProcService))
2416
{
@@ -29,11 +21,34 @@ public static BrokeredServiceConfiguration BrokeredServiceConfiguration
2921

3022
public async Task SetCodeItemIsExpanded(int spanStart, int spanEnd, bool isExpanded)
3123
{
32-
OutliningHelper.SetIsExpanded(_codeDocumentService.CodeDocumentViewModel, spanStart, spanEnd, isExpanded);
24+
OutliningService.SetIsExpanded(codeDocumentService.CodeDocumentViewModel, spanStart, spanEnd, isExpanded);
25+
}
26+
27+
public async Task ProcessActiveFrameChanged(string documentViewJsonString)
28+
{
29+
var documentView = JsonSerializer.Deserialize<DocumentView>(documentViewJsonString);
30+
31+
// Conditions:
32+
// - Frame is null
33+
// - Frame did not change
34+
// - Frame is not a document frame
35+
// Actions:
36+
// - Do nothing
37+
if (documentView?.IsDocumentFrame != true)
38+
{
39+
return;
40+
}
41+
42+
// Frame has changed and has a text document, so we need to update the list of code items
43+
await codeDocumentService.UpdateCodeDocumentViewModel(
44+
extensibility,
45+
documentView.FilePath,
46+
documentView.Text,
47+
default);
3348
}
3449

3550
public async Task DoSomethingAsync(CancellationToken cancellationToken)
3651
{
37-
await _extensibility.Shell().ShowPromptAsync("Hello from in-proc! (Showing this message from (out-of-proc)", PromptOptions.OK, cancellationToken);
52+
await extensibility.Shell().ShowPromptAsync("Hello from in-proc! (Showing this message from (out-of-proc)", PromptOptions.OK, cancellationToken);
3853
}
3954
}

src/CodeNav.OutOfProc/Helpers/OutliningHelper.cs renamed to src/CodeNav.OutOfProc/Services/OutliningService.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@
88
using Microsoft.VisualStudio.Extensibility.Helpers;
99
using System.Text.Json;
1010

11-
namespace CodeNav.OutOfProc.Helpers;
11+
namespace CodeNav.OutOfProc.Services;
1212

13-
public class OutliningHelper : DisposableObject
13+
public class OutliningService : DisposableObject
1414
{
1515
private readonly VisualStudioExtensibility _extensibility;
1616
private readonly Task _initializationTask;
1717
private IInProcService? _inProcService;
1818

19-
public OutliningHelper(VisualStudioExtensibility extensibility)
19+
public OutliningService(VisualStudioExtensibility extensibility)
2020
{
2121
_extensibility = extensibility;
2222
_initializationTask = Task.Run(InitializeAsync);
@@ -83,29 +83,29 @@ public async Task ExpandOutlineRegion(int start, int length)
8383

8484
public static async Task CollapseOutlineRegion(CodeItem codeItem)
8585
{
86-
if (codeItem.CodeDocumentViewModel?.CodeDocumentService?.OutliningHelper == null)
86+
if (codeItem.CodeDocumentViewModel?.CodeDocumentService?.OutliningService == null)
8787
{
8888
return;
8989
}
9090

9191
await codeItem
9292
.CodeDocumentViewModel
9393
.CodeDocumentService
94-
.OutliningHelper
94+
.OutliningService
9595
.CollapseOutlineRegion(codeItem.OutlineSpan.Start, codeItem.OutlineSpan.Length);
9696
}
9797

9898
public static async Task ExpandOutlineRegion(CodeItem codeItem)
9999
{
100-
if (codeItem.CodeDocumentViewModel?.CodeDocumentService?.OutliningHelper == null)
100+
if (codeItem.CodeDocumentViewModel?.CodeDocumentService?.OutliningService == null)
101101
{
102102
return;
103103
}
104104

105105
await codeItem
106106
.CodeDocumentViewModel
107107
.CodeDocumentService
108-
.OutliningHelper
108+
.OutliningService
109109
.ExpandOutlineRegion(codeItem.OutlineSpan.Start, codeItem.OutlineSpan.Length);
110110
}
111111

0 commit comments

Comments
 (0)