File: InProcess\EditorInProcess_Caret.cs
Web Access
Project: src\src\Razor\src\Razor\test\Microsoft.VisualStudio.Razor.IntegrationTests\Microsoft.VisualStudio.Razor.IntegrationTests.csproj (Microsoft.VisualStudio.Razor.IntegrationTests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.Razor.IntegrationTests.Extensions;
 
namespace Microsoft.VisualStudio.Extensibility.Testing;
 
internal partial class EditorInProcess
{
    public async Task PlaceCaretAsync(int position, CancellationToken cancellationToken)
    {
        await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
 
        var view = await GetActiveTextViewAsync(cancellationToken);
        view.Caret.MoveTo(new SnapshotPoint(view.GetBufferContainingCaret()!.CurrentSnapshot, position));
 
        await ActivateAsync(cancellationToken);
    }
 
    public Task PlaceCaretAsync(string marker, int charsOffset, CancellationToken cancellationToken)
        => PlaceCaretAsync(marker, charsOffset, occurrence: 0, extendSelection: false, selectBlock: false, cancellationToken);
 
    public async Task PlaceCaretAsync(
        string marker,
        int charsOffset,
        int occurrence,
        bool extendSelection,
        bool selectBlock,
        CancellationToken cancellationToken)
    {
        await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
 
        var view = await GetActiveTextViewAsync(cancellationToken);
 
        var dte = await GetRequiredGlobalServiceAsync<SDTE, EnvDTE.DTE>(cancellationToken);
        dte.Find.FindWhat = marker;
        dte.Find.MatchCase = true;
        dte.Find.MatchInHiddenText = true;
        dte.Find.Target = EnvDTE.vsFindTarget.vsFindTargetCurrentDocument;
        dte.Find.Action = EnvDTE.vsFindAction.vsFindActionFind;
 
        var originalPosition = await GetCaretPositionAsync(cancellationToken);
        view.Caret.MoveTo(new SnapshotPoint(view.GetBufferContainingCaret()!.CurrentSnapshot, 0));
 
        if (occurrence > 0)
        {
            var result = EnvDTE.vsFindResult.vsFindResultNotFound;
            for (var i = 0; i < occurrence; i++)
            {
                result = dte.Find.Execute();
            }
 
            if (result != EnvDTE.vsFindResult.vsFindResultFound)
            {
                throw new Exception("Occurrence " + occurrence + " of marker '" + marker + "' not found in text: " + view.TextSnapshot.GetText());
            }
        }
        else
        {
            var result = dte.Find.Execute();
            if (result != EnvDTE.vsFindResult.vsFindResultFound)
            {
                throw new Exception("Marker '" + marker + "' not found in text: " + view.TextSnapshot.GetText());
            }
        }
 
        if (charsOffset > 0)
        {
            for (var i = 0; i < charsOffset - 1; i++)
            {
                view.Caret.MoveToNextCaretPosition();
            }
 
            view.Selection.Clear();
        }
 
        if (charsOffset < 0)
        {
            // On the first negative charsOffset, move to anchor-point position, as if the user hit the LEFT key
            view.Caret.MoveTo(new SnapshotPoint(view.TextSnapshot, view.Selection.AnchorPoint.Position.Position));
 
            for (var i = 0; i < -charsOffset - 1; i++)
            {
                view.Caret.MoveToPreviousCaretPosition();
            }
 
            view.Selection.Clear();
        }
 
        if (extendSelection)
        {
            var newPosition = view.Selection.ActivePoint.Position.Position;
            view.Selection.Select(new VirtualSnapshotPoint(view.TextSnapshot, originalPosition), new VirtualSnapshotPoint(view.TextSnapshot, newPosition));
            view.Selection.Mode = selectBlock ? TextSelectionMode.Box : TextSelectionMode.Stream;
        }
    }
 
    public async Task<int> GetCaretPositionAsync(CancellationToken cancellationToken)
    {
        await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
 
        var view = await GetActiveTextViewAsync(cancellationToken);
 
        var subjectBuffer = view.GetBufferContainingCaret();
        Assumes.Present(subjectBuffer);
 
        var bufferPosition = view.Caret.Position.BufferPosition;
        return bufferPosition.Position;
    }
}