|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.IntegrationTest.Utilities.Common;
using Microsoft.VisualStudio.IntegrationTest.Utilities.InProcess;
using Microsoft.VisualStudio.IntegrationTest.Utilities.Input;
using Xunit;
namespace Microsoft.VisualStudio.IntegrationTest.Utilities.OutOfProcess
{
/// <summary>
/// Provides a means of interacting with the Visual Studio editor by remoting calls into Visual Studio.
/// </summary>
public partial class Editor_OutOfProc : TextViewWindow_OutOfProc
{
public new Verifier Verify { get; }
private readonly Editor_InProc _editorInProc;
private readonly VisualStudioInstance _instance;
internal Editor_OutOfProc(VisualStudioInstance visualStudioInstance)
: base(visualStudioInstance)
{
_instance = visualStudioInstance;
_editorInProc = (Editor_InProc)_textViewWindowInProc;
Verify = new Verifier(this, _instance);
}
internal override TextViewWindow_InProc CreateInProcComponent(VisualStudioInstance visualStudioInstance)
=> CreateInProcComponent<Editor_InProc>(visualStudioInstance);
public void Activate()
=> _editorInProc.Activate();
public string GetText()
=> _editorInProc.GetText();
public void SetText(string value)
=> _editorInProc.SetText(value);
public string GetCurrentLineText()
=> _editorInProc.GetCurrentLineText();
public string GetLineTextBeforeCaret()
=> _editorInProc.GetLineTextBeforeCaret();
public string GetLineTextAfterCaret()
=> _editorInProc.GetLineTextAfterCaret();
public void MoveCaret(int position)
=> _editorInProc.MoveCaret(position);
public ImmutableArray<TextSpan> GetTagSpans(string tagId)
{
if (tagId == InlineRenameDialog_OutOfProc.ValidRenameTag)
{
_instance.Workspace.WaitForAsyncOperations(Helper.HangMitigatingTimeout, FeatureAttribute.Rename);
}
var tagInfo = _editorInProc.GetTagSpans(tagId).ToList();
// The spans are returned in an array:
// [s1.Start, s1.Length, s2.Start, s2.Length, ...]
// Reconstruct the spans from their component parts
var builder = ArrayBuilder<TextSpan>.GetInstance();
for (var i = 0; i < tagInfo.Count; i += 2)
{
builder.Add(new TextSpan(tagInfo[i], tagInfo[i + 1]));
}
return builder.ToImmutableAndFree();
}
public void InvokeNavigateToNextHighlightedReference()
{
_instance.Workspace.WaitForAsyncOperations(Helper.HangMitigatingTimeout, FeatureAttribute.ReferenceHighlighting);
_instance.ExecuteCommand(WellKnownCommandNames.Edit_NextHighlightedReference);
}
public string GetCurrentCompletionItem()
{
WaitForCompletionSet();
return _editorInProc.GetCurrentCompletionItem();
}
public bool IsCompletionActive()
{
WaitForCompletionSet();
return _editorInProc.IsCompletionActive();
}
public void InvokeSignatureHelp()
{
_instance.ExecuteCommand(WellKnownCommandNames.Edit_ParameterInfo);
_instance.Workspace.WaitForAsyncOperations(Helper.HangMitigatingTimeout, FeatureAttribute.SignatureHelp);
}
public bool IsSignatureHelpActive()
{
WaitForSignatureHelp();
return _editorInProc.IsSignatureHelpActive();
}
public Signature GetCurrentSignature()
{
WaitForSignatureHelp();
return _editorInProc.GetCurrentSignature();
}
public void SelectTextInCurrentDocument(string text)
{
PlaceCaret(text, charsOffset: -1, occurrence: 0, extendSelection: false, selectBlock: false);
PlaceCaret(text, charsOffset: 0, occurrence: 0, extendSelection: true, selectBlock: false);
}
public int GetLine() => _editorInProc.GetLine();
public int GetColumn() => _editorInProc.GetColumn();
public void ReplaceText(string oldText, string newText)
=> _editorInProc.ReplaceText(oldText, newText);
public bool IsCaretOnScreen()
=> _editorInProc.IsCaretOnScreen();
public void AddWinFormButton(string buttonName)
=> _editorInProc.AddWinFormButton(buttonName);
public void DeleteWinFormButton(string buttonName)
=> _editorInProc.DeleteWinFormButton(buttonName);
public void EditWinFormButtonProperty(string buttonName, string propertyName, string propertyValue, string? propertyTypeName = null)
=> _editorInProc.EditWinFormButtonProperty(buttonName, propertyName, propertyValue, propertyTypeName);
public void EditWinFormButtonEvent(string buttonName, string eventName, string eventHandlerName)
=> _editorInProc.EditWinFormButtonEvent(buttonName, eventName, eventHandlerName);
public string? GetWinFormButtonPropertyValue(string buttonName, string propertyName)
=> _editorInProc.GetWinFormButtonPropertyValue(buttonName, propertyName);
/// <summary>
/// Sends key strokes to the active editor in Visual Studio. Various types are supported by this method:
/// <see cref="string"/> (each character will be sent separately, <see cref="char"/>, <see cref="VirtualKey"/>
/// and <see cref="KeyPress"/>.
/// </summary>
public void SendKeys(params object[] keys)
{
Activate();
VisualStudioInstance.SendKeys.Send(keys);
}
public void VerifyDialog(string dialogName, bool isOpen)
=> _editorInProc.VerifyDialog(dialogName, isOpen);
public void PressDialogButton(string dialogAutomationName, string buttonAutomationName)
=> _editorInProc.PressDialogButton(dialogAutomationName, buttonAutomationName);
public void DialogSendKeys(string dialogAutomationName, params object[] keys)
=> _editorInProc.DialogSendKeys(dialogAutomationName, keys);
public void Undo()
=> _editorInProc.Undo();
public void Redo()
=> _editorInProc.Redo();
public ClassifiedToken[] GetLightbulbPreviewClassification(string menuText)
=> _editorInProc.GetLightbulbPreviewClassifications(menuText);
public void SetUseSuggestionMode(bool value)
{
Assert.False(IsCompletionActive());
_editorInProc.SetUseSuggestionMode(value);
}
public TextSpan[] GetKeywordHighlightTags()
=> Deserialize(_editorInProc.GetHighlightTags());
public TextSpan[] GetOutliningSpans()
{
_instance.Workspace.WaitForAsyncOperations(Helper.HangMitigatingTimeout, FeatureAttribute.Outlining);
return Deserialize(_editorInProc.GetOutliningSpans());
}
private static TextSpan[] Deserialize(string[] v)
{
// returned tag looks something like 'text'[12-13]
return v.Select(tag =>
{
var open = tag.LastIndexOf('[') + 1;
var comma = tag.LastIndexOf('-');
var close = tag.LastIndexOf(']');
var start = tag[open..comma];
var end = tag.Substring(comma + 1, close - comma - 1);
return TextSpan.FromBounds(int.Parse(start), int.Parse(end));
}).ToArray();
}
}
}
|