Skip to content

Commit

Permalink
Port changes from interactive-window repo back to Roslyn (#13550)
Browse files Browse the repository at this point in the history
  • Loading branch information
tmat committed Sep 2, 2016
1 parent 1053db2 commit 2efc2ce
Show file tree
Hide file tree
Showing 67 changed files with 3,565 additions and 283 deletions.
34 changes: 20 additions & 14 deletions Roslyn.sln
Original file line number Diff line number Diff line change
Expand Up @@ -1676,20 +1676,26 @@ Global
{6E62A0FF-D0DC-4109-9131-AB8E60CDFF7B}.Release|x64.Build.0 = Release|Any CPU
{6E62A0FF-D0DC-4109-9131-AB8E60CDFF7B}.Release|x86.ActiveCfg = Release|Any CPU
{6E62A0FF-D0DC-4109-9131-AB8E60CDFF7B}.Release|x86.Build.0 = Release|Any CPU
{7F3CB45E-4993-4FA4-8D6A-C2DFFED2DFC3}.Debug|Any CPU.ActiveCfg = Debug|x86
{7F3CB45E-4993-4FA4-8D6A-C2DFFED2DFC3}.Debug|ARM.ActiveCfg = Debug|x86
{7F3CB45E-4993-4FA4-8D6A-C2DFFED2DFC3}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
{7F3CB45E-4993-4FA4-8D6A-C2DFFED2DFC3}.Debug|Mixed Platforms.Build.0 = Debug|x86
{7F3CB45E-4993-4FA4-8D6A-C2DFFED2DFC3}.Debug|x64.ActiveCfg = Debug|x86
{7F3CB45E-4993-4FA4-8D6A-C2DFFED2DFC3}.Debug|x86.ActiveCfg = Debug|x86
{7F3CB45E-4993-4FA4-8D6A-C2DFFED2DFC3}.Debug|x86.Build.0 = Debug|x86
{7F3CB45E-4993-4FA4-8D6A-C2DFFED2DFC3}.Release|Any CPU.ActiveCfg = Release|x86
{7F3CB45E-4993-4FA4-8D6A-C2DFFED2DFC3}.Release|ARM.ActiveCfg = Release|x86
{7F3CB45E-4993-4FA4-8D6A-C2DFFED2DFC3}.Release|Mixed Platforms.ActiveCfg = Release|x86
{7F3CB45E-4993-4FA4-8D6A-C2DFFED2DFC3}.Release|Mixed Platforms.Build.0 = Release|x86
{7F3CB45E-4993-4FA4-8D6A-C2DFFED2DFC3}.Release|x64.ActiveCfg = Release|x86
{7F3CB45E-4993-4FA4-8D6A-C2DFFED2DFC3}.Release|x86.ActiveCfg = Release|x86
{7F3CB45E-4993-4FA4-8D6A-C2DFFED2DFC3}.Release|x86.Build.0 = Release|x86
{7F3CB45E-4993-4FA4-8D6A-C2DFFED2DFC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7F3CB45E-4993-4FA4-8D6A-C2DFFED2DFC3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7F3CB45E-4993-4FA4-8D6A-C2DFFED2DFC3}.Debug|ARM.ActiveCfg = Debug|Any CPU
{7F3CB45E-4993-4FA4-8D6A-C2DFFED2DFC3}.Debug|ARM.Build.0 = Debug|Any CPU
{7F3CB45E-4993-4FA4-8D6A-C2DFFED2DFC3}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{7F3CB45E-4993-4FA4-8D6A-C2DFFED2DFC3}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{7F3CB45E-4993-4FA4-8D6A-C2DFFED2DFC3}.Debug|x64.ActiveCfg = Debug|Any CPU
{7F3CB45E-4993-4FA4-8D6A-C2DFFED2DFC3}.Debug|x64.Build.0 = Debug|Any CPU
{7F3CB45E-4993-4FA4-8D6A-C2DFFED2DFC3}.Debug|x86.ActiveCfg = Debug|Any CPU
{7F3CB45E-4993-4FA4-8D6A-C2DFFED2DFC3}.Debug|x86.Build.0 = Debug|Any CPU
{7F3CB45E-4993-4FA4-8D6A-C2DFFED2DFC3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7F3CB45E-4993-4FA4-8D6A-C2DFFED2DFC3}.Release|Any CPU.Build.0 = Release|Any CPU
{7F3CB45E-4993-4FA4-8D6A-C2DFFED2DFC3}.Release|ARM.ActiveCfg = Release|Any CPU
{7F3CB45E-4993-4FA4-8D6A-C2DFFED2DFC3}.Release|ARM.Build.0 = Release|Any CPU
{7F3CB45E-4993-4FA4-8D6A-C2DFFED2DFC3}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{7F3CB45E-4993-4FA4-8D6A-C2DFFED2DFC3}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{7F3CB45E-4993-4FA4-8D6A-C2DFFED2DFC3}.Release|x64.ActiveCfg = Release|Any CPU
{7F3CB45E-4993-4FA4-8D6A-C2DFFED2DFC3}.Release|x64.Build.0 = Release|Any CPU
{7F3CB45E-4993-4FA4-8D6A-C2DFFED2DFC3}.Release|x86.ActiveCfg = Release|Any CPU
{7F3CB45E-4993-4FA4-8D6A-C2DFFED2DFC3}.Release|x86.Build.0 = Release|Any CPU
{20BB6FAC-44D2-4D76-ABFE-0C1E163A1A4F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{20BB6FAC-44D2-4D76-ABFE-0C1E163A1A4F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{20BB6FAC-44D2-4D76-ABFE-0C1E163A1A4F}.Debug|ARM.ActiveCfg = Debug|Any CPU
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

extern alias InteractiveWindow;

using System;
using System.ComponentModel.Composition;
using System.Diagnostics;
Expand All @@ -14,6 +12,8 @@
using Microsoft.VisualStudio.Utilities;
using Microsoft.CodeAnalysis.Collections;
using Microsoft.CodeAnalysis.Editor.Commands;
using System.IO;
using Microsoft.VisualStudio.InteractiveWindow;

namespace Microsoft.CodeAnalysis.Editor.CommandHandlers
{
Expand All @@ -27,11 +27,6 @@ namespace Microsoft.CodeAnalysis.Editor.CommandHandlers
[Order(After = PredefinedCommandHandlerNames.Completion)]
internal sealed class InteractivePasteCommandHandler : ICommandHandler<PasteCommandArgs>
{
// Duplicated string, originally defined at `Microsoft.VisualStudio.InteractiveWindow.PredefinedInteractiveContentTypes`
private const string InteractiveContentTypeName = "Interactive Content";
// Duplicated string, originally defined at `Microsoft.VisualStudio.InteractiveWindow.InteractiveWindow`
private const string InteractiveClipboardFormat = "89344A36-9821-495A-8255-99A63969F87D";

// The following two field definitions have to stay in sync with VS editor implementation

/// <summary>
Expand Down Expand Up @@ -63,8 +58,8 @@ public InteractivePasteCommandHandler(IEditorOperationsFactoryService editorOper
public void ExecuteCommand(PasteCommandArgs args, Action nextHandler)
{
// InteractiveWindow handles pasting by itself, which including checks for buffer types, etc.
if (!args.TextView.TextBuffer.ContentType.IsOfType(InteractiveContentTypeName) &&
RoslynClipboard.ContainsData(InteractiveClipboardFormat))
if (!args.TextView.TextBuffer.ContentType.IsOfType(PredefinedInteractiveContentTypes.InteractiveContentTypeName) &&
RoslynClipboard.ContainsData(InteractiveClipboardFormat.Tag))
{
PasteInteractiveFormat(args.TextView);
}
Expand Down Expand Up @@ -94,27 +89,15 @@ private void PasteInteractiveFormat(ITextView textView)
dataHasBoxCutCopyTag = data.GetDataPresent(BoxSelectionCutCopyTag);
Debug.Assert(!(dataHasLineCutCopyTag && dataHasBoxCutCopyTag));

var blocks = InteractiveWindow::Microsoft.VisualStudio.InteractiveWindow.BufferBlock.Deserialize((string)RoslynClipboard.GetData(InteractiveClipboardFormat));

var sb = PooledStringBuilder.GetInstance();
foreach (var block in blocks)
string text;
try
{
switch (block.Kind)
{
// the actual linebreak was converted to regular Input when copied
// This LineBreak block was created by coping box selection and is used as line separater when pasted
case InteractiveWindow::Microsoft.VisualStudio.InteractiveWindow.ReplSpanKind.LineBreak:
Debug.Assert(dataHasBoxCutCopyTag);
sb.Builder.Append(block.Content);
break;
case InteractiveWindow::Microsoft.VisualStudio.InteractiveWindow.ReplSpanKind.Input:
case InteractiveWindow::Microsoft.VisualStudio.InteractiveWindow.ReplSpanKind.Output:
case InteractiveWindow::Microsoft.VisualStudio.InteractiveWindow.ReplSpanKind.StandardInput:
sb.Builder.Append(block.Content);
break;
}
text = InteractiveClipboardFormat.Deserialize(RoslynClipboard.GetData(InteractiveClipboardFormat.Tag));
}
catch (InvalidDataException)
{
text = "<bad clipboard data>";
}
var text = sb.ToStringAndFree();

using (var transaction = _textUndoHistoryRegistry.GetHistory(textView.TextBuffer).CreateTransaction(EditorFeaturesResources.Paste))
{
Expand Down
1 change: 0 additions & 1 deletion src/EditorFeatures/Core/EditorFeatures.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@
<ProjectReference Include="..\..\InteractiveWindow\Editor\InteractiveWindow.csproj">
<Project>{01E9BD68-0339-4A13-B42F-A3CA84D164F3}</Project>
<Name>InteractiveWindow</Name>
<Aliases>InteractiveWindow</Aliases>
</ProjectReference>
</ItemGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@ Imports Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces

Namespace Microsoft.CodeAnalysis.Editor.UnitTests.InteractivePaste
Public Class InteractivePasteCommandhandlerTests
Const ClipboardLineBasedCutCopyTag As String = "VisualStudioEditorOperationsLineCutCopyClipboardTag"
Const BoxSelectionCutCopyTag As String = "MSDEVColumnSelect"

Private Function CreateCommandHandler(workspace As TestWorkspace) As InteractivePasteCommandHandler
Dim handler = New InteractivePasteCommandHandler(workspace.GetService(Of IEditorOperationsFactoryService),
workspace.GetService(Of ITextUndoHistoryRegistry))
handler.RoslynClipBoard = New MockClipboard()
handler.RoslynClipboard = New MockClipboard()
Return handler
End Function

Expand All @@ -32,15 +35,19 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.InteractivePaste
Dim handler = CreateCommandHandler(workspace)
Dim clipboard = DirectCast(handler.RoslynClipboard, MockClipboard)

Dim blocks = New BufferBlock() _
{
New BufferBlock(ReplSpanKind.Output, "a" & vbCrLf & "bc"),
New BufferBlock(ReplSpanKind.Prompt, "> "),
New BufferBlock(ReplSpanKind.Prompt, "< "),
New BufferBlock(ReplSpanKind.Input, "12"),
New BufferBlock(ReplSpanKind.StandardInput, "3")
}
CopyToClipboard(clipboard, blocks, includeRepl:=True, isLineCopy:=False, isBoxCopy:=False)

Dim json = "
[
{""content"":""a\u000d\u000abc"",""kind"":1},
{""content"":""> "",""kind"":0},
{""content"":""< "",""kind"":0},
{""content"":""12"",""kind"":2},
{""content"":""3"",""kind"":3},
]"

Dim text = $"a{vbCrLf}bc123"

CopyToClipboard(clipboard, text, json, includeRepl:=True, isLineCopy:=False, isBoxCopy:=False)

handler.ExecuteCommand(New PasteCommandArgs(textView, textView.TextBuffer), Sub() Throw New Exception("The operation should have been handled."))

Expand All @@ -64,15 +71,17 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.InteractivePaste
Dim handler = CreateCommandHandler(workspace)
Dim clipboard = DirectCast(handler.RoslynClipboard, MockClipboard)

Dim blocks = New BufferBlock() _
{
New BufferBlock(ReplSpanKind.Output, "a" & vbCrLf & "bc"),
New BufferBlock(ReplSpanKind.Prompt, "> "),
New BufferBlock(ReplSpanKind.Prompt, "< "),
New BufferBlock(ReplSpanKind.Input, "12"),
New BufferBlock(ReplSpanKind.StandardInput, "3")
}
CopyToClipboard(clipboard, blocks, includeRepl:=False, isLineCopy:=False, isBoxCopy:=False)
Dim json = "
[
{""content"":""a\u000d\u000abc"",""kind"":1},
{""content"":""> "",""kind"":0},
{""content"":""< "",""kind"":0},
{""content"":""12"",""kind"":2},
{""content"":""3"",""kind"":3}]
]"
Dim text = $"a{vbCrLf}bc123"

CopyToClipboard(clipboard, Text, json, includeRepl:=False, isLineCopy:=False, isBoxCopy:=False)

handler.ExecuteCommand(New PasteCommandArgs(textView, textView.TextBuffer), Sub() editorOperations.InsertText("p"))

Expand Down Expand Up @@ -102,13 +111,15 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.InteractivePaste
Dim handler = CreateCommandHandler(workspace)
Dim clipboard = DirectCast(handler.RoslynClipboard, MockClipboard)

Dim blocks = New BufferBlock() _
{
New BufferBlock(ReplSpanKind.Prompt, "> "),
New BufferBlock(ReplSpanKind.Input, "InsertedLine"),
New BufferBlock(ReplSpanKind.Output, vbCrLf)
}
CopyToClipboard(clipboard, blocks, includeRepl:=True, isLineCopy:=True, isBoxCopy:=False)
Dim json = "
[
{""content"":""> "",""kind"":0},
{""content"":""InsertedLine"",""kind"":2},
{""content"":""\u000d\u000a"",""kind"":4}]
]"
Dim text = $"InsertedLine{vbCrLf}"

CopyToClipboard(clipboard, text, json, includeRepl:=True, isLineCopy:=True, isBoxCopy:=False)

handler.ExecuteCommand(New PasteCommandArgs(textView, textView.TextBuffer), Sub() Throw New Exception("The operation should have been handled."))

Expand Down Expand Up @@ -140,16 +151,18 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.InteractivePaste
Dim handler = CreateCommandHandler(workspace)
Dim clipboard = DirectCast(handler.RoslynClipboard, MockClipboard)

Dim blocks = New BufferBlock() _
{
New BufferBlock(ReplSpanKind.Prompt, "> "),
New BufferBlock(ReplSpanKind.Input, "BoxLine1"),
New BufferBlock(ReplSpanKind.LineBreak, vbCrLf),
New BufferBlock(ReplSpanKind.Prompt, "> "),
New BufferBlock(ReplSpanKind.Input, "BoxLine2"),
New BufferBlock(ReplSpanKind.LineBreak, vbCrLf)
}
CopyToClipboard(clipboard, blocks, includeRepl:=True, isLineCopy:=False, isBoxCopy:=True)
Dim json = "
[
{""content"":""> "",""kind"":0},
{""content"":""BoxLine1"",""kind"":2},
{""content"":""\u000d\u000a"",""kind"":4},
{""content"":""> "",""kind"":0},
{""content"":""BoxLine2"",""kind"":2},
{""content"":""\u000d\u000a"",""kind"":4}]
]"
Dim text = $"BoxLine1{vbCrLf}BoxLine2{vbCrLf}"

CopyToClipboard(clipboard, text, json, includeRepl:=True, isLineCopy:=False, isBoxCopy:=True)

handler.ExecuteCommand(New PasteCommandArgs(textView, textView.TextBuffer), Sub() Throw New Exception("The operation should have been handled."))

Expand Down Expand Up @@ -182,45 +195,47 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.InteractivePaste
Dim handler = CreateCommandHandler(workspace)
Dim clipboard = DirectCast(handler.RoslynClipboard, MockClipboard)

Dim blocks = New BufferBlock() _
{
New BufferBlock(ReplSpanKind.Prompt, "> "),
New BufferBlock(ReplSpanKind.Input, "BoxLine1"),
New BufferBlock(ReplSpanKind.LineBreak, vbCrLf),
New BufferBlock(ReplSpanKind.Prompt, "> "),
New BufferBlock(ReplSpanKind.Input, "BoxLine2"),
New BufferBlock(ReplSpanKind.LineBreak, vbCrLf)
}
CopyToClipboard(clipboard, blocks, includeRepl:=True, isLineCopy:=False, isBoxCopy:=True)
Dim json = "
[
{""content"":""> "",""kind"":0},
{""content"":""BoxLine1"",""kind"":2},
{""content"":""\u000d\u000a"",""kind"":4},
{""content"":""> "",""kind"":0},
{""content"":""BoxLine2"",""kind"":2},
{""content"":""\u000d\u000a"",""kind"":4}
]"

Dim text = $"> BoxLine1{vbCrLf}> BoxLine2{vbCrLf}"

CopyToClipboard(clipboard, text, json, includeRepl:=True, isLineCopy:=False, isBoxCopy:=True)

handler.ExecuteCommand(New PasteCommandArgs(textView, textView.TextBuffer), Sub() Throw New Exception("The operation should have been handled."))

Assert.Equal("BoxLine1" & vbCrLf & "BoxLine2" & vbCrLf & "line1" & vbCrLf & " line2", textView.TextBuffer.CurrentSnapshot.GetText())
End Using
End Function

Private Sub CopyToClipboard(clipboard As MockClipboard, blocks As BufferBlock(), includeRepl As Boolean, isLineCopy As Boolean, isBoxCopy As Boolean)
Private Sub CopyToClipboard(clipboard As MockClipboard, text As String, json As String, includeRepl As Boolean, isLineCopy As Boolean, isBoxCopy As Boolean)
clipboard.Clear()

Dim data = New DataObject()
Dim builder = New StringBuilder()
For Each block As BufferBlock In blocks
builder.Append(block.Content)
Next
Dim text = builder.ToString()

data.SetData(DataFormats.UnicodeText, text)
data.SetData(DataFormats.StringFormat, text)
If includeRepl Then
data.SetData(InteractiveWindow.ClipboardFormat, BufferBlock.Serialize(blocks))
data.SetData(InteractiveClipboardFormat.Tag, json)
End If
If isLineCopy Then
data.SetData(InteractiveWindow.ClipboardLineBasedCutCopyTag, True)
data.SetData(ClipboardLineBasedCutCopyTag, True)
End If
If isBoxCopy Then
data.SetData(InteractiveWindow.BoxSelectionCutCopyTag, True)
data.SetData(BoxSelectionCutCopyTag, True)
End If
clipboard.SetDataObject(data)
End Sub


Private Class MockClipboard
Implements InteractivePasteCommandHandler.IRoslynClipboard

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ internal InteractiveEvaluator(
_interactiveHost.ProcessStarting += ProcessStarting;
}

public int SubmissionCount => _submissionCount;

public IContentType ContentType
{
get
Expand Down
17 changes: 13 additions & 4 deletions src/InteractiveWindow/Editor/BufferBlock.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// 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;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
Expand Down Expand Up @@ -35,14 +36,22 @@ internal static string Serialize(BufferBlock[] blocks)
}
}

/// <exception cref="InvalidDataException" />
internal static BufferBlock[] Deserialize(string str)
{
var serializer = new DataContractJsonSerializer(typeof(BufferBlock[]));
var bytes = Encoding.UTF8.GetBytes(str);
using (var stream = new MemoryStream(bytes))
try
{
var obj = serializer.ReadObject(stream);
return (BufferBlock[])obj;
var bytes = Encoding.UTF8.GetBytes(str);
using (var stream = new MemoryStream(bytes))
{
var obj = serializer.ReadObject(stream);
return (BufferBlock[])obj;
}
}
catch (Exception e)
{
throw new InvalidDataException(e.Message, e);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
using System.ComponentModel.Composition;
using Microsoft.VisualStudio.Utilities;

#pragma warning disable CS0649 // field is not assigned to

namespace Microsoft.VisualStudio.InteractiveWindow.Commands
{
public static class PredefinedInteractiveCommandsContentTypes
Expand Down
Loading

0 comments on commit 2efc2ce

Please sign in to comment.