提交 4ecbb2df 编写于 作者: A Andrew Casey

Merge pull request #4909 from amcasey/RemainingUIOnly

Move remaining InteractiveWindow behavior to the UI thread
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Projection;
namespace Microsoft.VisualStudio.InteractiveWindow
{
internal partial class InteractiveWindow
{
private sealed class EditResolver : IProjectionEditResolver
{
private readonly InteractiveWindow _window;
public EditResolver(InteractiveWindow window)
{
_window = window;
}
// We always favor the last buffer of our language type. This handles cases where we're on a boundary between a prompt and a language
// buffer - we favor the language buffer because the prompts cannot be edited. In the case of two language buffers this also works because
// our spans are laid out like:
// <lang span 1 including newline>
// <prompt span><lang span 2>
//
// In the case where the prompts are in the margin we have an insertion conflict between the two language spans. But because
// lang span 1 includes the new line in order to be oun the boundary we need to be on lang span 2's line.
//
// This works the same way w/ our input buffer where the input buffer present instead of <lang span 2>.
void IProjectionEditResolver.FillInInsertionSizes(SnapshotPoint projectionInsertionPoint, ReadOnlyCollection<SnapshotPoint> sourceInsertionPoints, string insertionText, IList<int> insertionSizes)
{
int index = _window.UIThread(uiOnly => IndexOfEditableBuffer(sourceInsertionPoints, uiOnly));
if (index != -1)
{
insertionSizes[index] = insertionText.Length;
}
}
int IProjectionEditResolver.GetTypicalInsertionPosition(SnapshotPoint projectionInsertionPoint, ReadOnlyCollection<SnapshotPoint> sourceInsertionPoints)
{
int index = _window.UIThread(uiOnly => IndexOfEditableBuffer(sourceInsertionPoints, uiOnly));
return index != -1 ? index : 0;
}
void IProjectionEditResolver.FillInReplacementSizes(SnapshotSpan projectionReplacementSpan, ReadOnlyCollection<SnapshotSpan> sourceReplacementSpans, string insertionText, IList<int> insertionSizes)
{
int index = _window.UIThread(uiOnly => IndexOfEditableBuffer(sourceReplacementSpans, uiOnly));
if (index != -1)
{
insertionSizes[index] = insertionText.Length;
}
}
private int IndexOfEditableBuffer(ReadOnlyCollection<SnapshotPoint> points, UIThreadOnly uiOnly)
{
Debug.Assert(_window.OnUIThread());
for (int i = points.Count - 1; i >= 0; i--)
{
if (IsEditableBuffer(points[i].Snapshot.TextBuffer, uiOnly))
{
return i;
}
}
return -1;
}
private int IndexOfEditableBuffer(ReadOnlyCollection<SnapshotSpan> spans, UIThreadOnly uiOnly)
{
Debug.Assert(_window.OnUIThread());
for (int i = spans.Count - 1; i >= 0; i--)
{
if (IsEditableBuffer(spans[i].Snapshot.TextBuffer, uiOnly))
{
return i;
}
}
return -1;
}
private bool IsEditableBuffer(ITextBuffer buffer, UIThreadOnly uiOnly)
{
return buffer == uiOnly.CurrentLanguageBuffer || buffer == uiOnly.StandardInputBuffer;
}
}
}
}
\ No newline at end of file
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Threading.Tasks;
namespace Microsoft.VisualStudio.InteractiveWindow
{
internal partial class InteractiveWindow
{
private class PendingSubmission
{
public readonly string Input;
/// <remarks>
/// Set only on the last submission in each batch (to notify the caller).
/// </remarks>
public readonly TaskCompletionSource<object> Completion;
public Task Task;
public PendingSubmission(string input, TaskCompletionSource<object> completion)
{
Input = input;
Completion = completion;
}
}
}
}
\ No newline at end of file
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.VisualStudio.InteractiveWindow
{
internal partial class InteractiveWindow
{
private enum ReplSpanKind
{
/// <summary>
/// Primary, secondary, or standard input prompt.
/// </summary>
Prompt,
/// <summary>
/// Line break inserted at end of output.
/// </summary>
LineBreak,
/// <summary>
/// The span represents output from the program (standard output).
/// </summary>
Output,
/// <summary>
/// The span represents code inputted after a prompt or secondary prompt.
/// </summary>
Language,
/// <summary>
/// The span represents the input for a standard input (non code input).
/// </summary>
StandardInput,
}
}
}
\ No newline at end of file
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.VisualStudio.InteractiveWindow
{
internal partial class InteractiveWindow
{
private struct SpanRangeEdit
{
public readonly int Start;
public readonly int End;
public readonly object[] Replacement;
public SpanRangeEdit(int start, int count, object[] replacement)
{
Start = start;
End = start + count;
Replacement = replacement;
}
}
}
}
\ No newline at end of file
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.VisualStudio.InteractiveWindow
{
internal partial class InteractiveWindow
{
internal enum State
{
/// <summary>
/// Initial state. <see cref="IInteractiveWindow.InitializeAsync"/> hasn't been called.
/// Transition to <see cref="Initializing"/> when <see cref="IInteractiveWindow.InitializeAsync"/> is called.
/// Transition to <see cref="Resetting"/> when <see cref="IInteractiveWindowOperations.ResetAsync"/> is called.
/// </summary>
Starting,
/// <summary>
/// In the process of calling <see cref="IInteractiveWindow.InitializeAsync"/>.
/// Transition to <see cref="WaitingForInput"/> when finished (in <see cref="UIThreadOnly.ProcessPendingSubmissions"/>).
/// Transition to <see cref="Resetting"/> when <see cref="IInteractiveWindowOperations.ResetAsync"/> is called.
/// </summary>
Initializing,
/// <summary>
/// In the process of calling <see cref="IInteractiveWindowOperations.ResetAsync"/>.
/// Transition to <see cref="WaitingForInput"/> when finished (in <see cref="UIThreadOnly.ProcessPendingSubmissions"/>).
/// Transition to <see cref="ResettingAndReadingStandardInput"/> when <see cref="IInteractiveWindow.ReadStandardInput"/> is called
/// </summary>
Resetting,
/// <summary>
/// Prompt has been displayed - waiting for the user to make the next submission.
/// Transition to <see cref="ExecutingInput"/> when <see cref="IInteractiveWindowOperations.ExecuteInput"/> is called.
/// Transition to <see cref="Resetting"/> when <see cref="IInteractiveWindowOperations.ResetAsync"/> is called.
/// Transition to <see cref="WaitingForInputAndReadingStandardInput"/> when <see cref="IInteractiveWindow.ReadStandardInput"/> is called
/// </summary>
WaitingForInput,
/// <summary>
/// Executing the user's submission.
/// Transition to <see cref="WaitingForInput"/> when finished (in <see cref="UIThreadOnly.ProcessPendingSubmissions"/>).
/// Transition to <see cref="Resetting"/> when <see cref="IInteractiveWindowOperations.ResetAsync"/> is called.
/// Transition to <see cref="ExecutingInputAndReadingStandardInput"/> when <see cref="IInteractiveWindow.ReadStandardInput"/> is called
/// </summary>
ExecutingInput,
/// <summary>
/// In the process of calling <see cref="IInteractiveWindow.ReadStandardInput"/> (within <see cref="IInteractiveWindowOperations.ResetAsync"/>).
/// Transition to <see cref="Resetting"/> when <see cref="IInteractiveWindowOperations.ClearView"/>,
/// <see cref="IInteractiveWindowOperations.TrySubmitStandardInput"/>, or
/// <see cref="IInteractiveWindowOperations.ResetAsync"/> is called.
/// </summary>
ResettingAndReadingStandardInput,
/// <summary>
/// In the process of calling <see cref="IInteractiveWindow.ReadStandardInput"/> (while prompt has been displayed).
/// Transition to <see cref="WaitingForInput"/> when <see cref="IInteractiveWindowOperations.ClearView"/> or <see cref="IInteractiveWindowOperations.TrySubmitStandardInput"/> is called.
/// Transition to <see cref="Resetting"/> when <see cref="IInteractiveWindowOperations.ResetAsync"/> is called.
/// </summary>
WaitingForInputAndReadingStandardInput,
/// <summary>
/// In the process of calling <see cref="IInteractiveWindow.ReadStandardInput"/> (while executing the user's submission).
/// Transition to <see cref="ExecutingInput"/> when <see cref="IInteractiveWindowOperations.ClearView"/> or <see cref="IInteractiveWindowOperations.TrySubmitStandardInput"/> is called.
/// Transition to <see cref="Resetting"/> when <see cref="IInteractiveWindowOperations.ResetAsync"/> is called.
/// </summary>
ExecutingInputAndReadingStandardInput,
}
}
}
......@@ -90,7 +90,13 @@
<Compile Include="Commands\InteractiveCommandsFactory.cs" />
<Compile Include="IInteractiveWindowOperations.cs" />
<Compile Include="IInteractiveWindowOperations2.cs" />
<Compile Include="InteractiveWindow_UIThread.cs" />
<Compile Include="InteractiveWindow.SpanRangeEdit.cs" />
<Compile Include="ProjectionBufferExtensions.cs" />
<Compile Include="InteractiveWindow.PendingSubmission.cs" />
<Compile Include="InteractiveWindow.ReplSpanKind.cs" />
<Compile Include="InteractiveWindow.EditResolver.cs" />
<Compile Include="InteractiveWindow.State.cs" />
<Compile Include="InteractiveWindow.UIThreadOnly.cs" />
<Compile Include="PredefinedInteractiveContentTypes.cs" />
<Compile Include="InteractiveContentTypeDefinitions.cs" />
<Compile Include="InteractiveWindow.cs" />
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Projection;
namespace Microsoft.VisualStudio.InteractiveWindow
{
internal static class ProjectionBufferExtensions
{
internal static SnapshotSpan GetSourceSpan(this IProjectionSnapshot snapshot, int index)
{
return snapshot.GetSourceSpans(index, 1)[0];
}
}
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册