Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion src/CodeNav.OutOfProc/ViewModels/CodeItem.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using CodeNav.OutOfProc.Constants;
using CodeNav.OutOfProc.Helpers;
using CodeNav.OutOfProc.Services;
using CodeNav.Services;
using Microsoft;
using Microsoft.CodeAnalysis.Text;
Expand Down Expand Up @@ -76,8 +75,20 @@ public CodeItem()
[DataMember]
public string Tooltip { get; set; } = string.Empty;

/// <summary>
/// Path to the file containing the code item
/// </summary>
/// <remarks>
/// Used for opening the file if it's different from the currently active one
/// </remarks>
public Uri? FilePath { get; set; }

/// <summary>
/// Full name of the code item
/// </summary>
/// <remarks>
/// Used in constructing a unique id
/// </remarks>
internal string FullName = string.Empty;

public CodeItemKindEnum Kind;
Expand Down
4 changes: 4 additions & 0 deletions src/CodeNav/Services/IInProcService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ public interface IInProcService

Task TextViewScrollToSpan(int start, int length);

Task ExpandOutlineRegion(int start, int length);

Task CollapseOutlineRegion(int start, int length);

public static class Configuration
{
public const string ServiceName = "CodeNav.InProcService";
Expand Down
77 changes: 75 additions & 2 deletions src/CodeNav/Services/InProcService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.Text.Outlining;
using Microsoft.VisualStudio.TextManager.Interop;

namespace CodeNav.Services;
Expand All @@ -16,15 +17,18 @@ internal class InProcService : IInProcService
{
private readonly VisualStudioExtensibility _extensibility;
private readonly MefInjection<IVsEditorAdaptersFactoryService> _editorAdaptersFactoryService;
private readonly MefInjection<IOutliningManagerService> _outliningManagerFactoryService;
private readonly AsyncServiceProviderInjection<SVsTextManager, IVsTextManager> _textManager;

public InProcService(
VisualStudioExtensibility extensibility,
MefInjection<IVsEditorAdaptersFactoryService> editorAdaptersFactoryService,
MefInjection<IOutliningManagerService> outliningManagerFactoryService,
AsyncServiceProviderInjection<SVsTextManager, IVsTextManager> textManager)
{
_extensibility = extensibility;
_editorAdaptersFactoryService = editorAdaptersFactoryService;
_outliningManagerFactoryService = outliningManagerFactoryService;
_textManager = textManager;
}

Expand All @@ -40,14 +44,83 @@ public async Task DoSomethingAsync(CancellationToken cancellationToken)
await _extensibility.Shell().ShowPromptAsync("Hello from out-of-proc! (Showing this message from (in-proc)", PromptOptions.OK, cancellationToken);
}

public async Task ExpandOutlineRegion(int start, int length)
{
try
{
// Not using context.GetActiveTextViewAsync here because VisualStudio.Extensibility doesn't support outlining yet.
var textView = await GetCurrentTextViewAsync();

var outliningManager = await GetOutliningManager(textView);

var outlineRegion = await GetOutlineRegionForSpan(textView, outliningManager, start, length);

// Check if the outline region is collapsed before expanding
if (outlineRegion?.IsCollapsed != true ||
outlineRegion is not ICollapsed collapsedOutlineRegion)
{
return;
}

outliningManager.Expand(collapsedOutlineRegion);
}
catch (Exception)
{
// TODO: Implement in-proc error logging
}
}

public async Task CollapseOutlineRegion(int start, int length)
{
try
{
// Not using context.GetActiveTextViewAsync here because VisualStudio.Extensibility doesn't support outlining yet.
var textView = await GetCurrentTextViewAsync();

var outliningManager = await GetOutliningManager(textView);

var outlineRegion = await GetOutlineRegionForSpan(textView, outliningManager, start, length);

outliningManager.TryCollapse(outlineRegion);
}
catch (Exception)
{
// TODO: Implement in-proc error logging
}
}

private async Task<ICollapsible?> GetOutlineRegionForSpan(
IWpfTextView textView, IOutliningManager outliningManager,
int start, int length)
{
// Get all outline regions for the given span
var span = new SnapshotSpan(textView.TextSnapshot, start, length);

var outlineRegions = outliningManager.GetAllRegions(span);

// Get the first outline region that has the same span start
return outlineRegions.FirstOrDefault(outlineRegion => GetSpan(outlineRegion).Start == start);
}

private SnapshotSpan GetSpan(ICollapsible outlineRegion)
=> outlineRegion.Extent.GetSpan(outlineRegion.Extent.TextBuffer.CurrentSnapshot);

private async Task<IOutliningManager> GetOutliningManager(IWpfTextView textView)
{
var outliningManagerService = await _outliningManagerFactoryService.GetServiceAsync();
var outliningManager = outliningManagerService.GetOutliningManager(textView);

return outliningManager;
}

public async Task TextViewScrollToSpan(int start, int length)
{
try
{
// Not using context.GetActiveTextViewAsync here because VisualStudio.Extensibility doesn't support viewscroller yet.
var textView = await GetCurrentTextViewAsync();

var span = new SnapshotSpan(textView.TextSnapshot, new Span(start, length));
var span = new SnapshotSpan(textView.TextSnapshot, start, length);

// Switch to the UI thread to ensure we can interact with the view scroller.
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
Expand All @@ -62,7 +135,7 @@ public async Task TextViewScrollToSpan(int start, int length)

private async Task<IWpfTextView> GetCurrentTextViewAsync()
{
IVsEditorAdaptersFactoryService editorAdapter = await _editorAdaptersFactoryService.GetServiceAsync();
var editorAdapter = await _editorAdaptersFactoryService.GetServiceAsync();
var view = editorAdapter.GetWpfTextView(await GetCurrentNativeTextViewAsync());
Assumes.Present(view);
return view;
Expand Down