提交 b2fc9978 编写于 作者: A Artur Spychaj

Test interactive commands

Expose test internals for ResetInteractive tests.
上级 9bc25d76
......@@ -148,6 +148,7 @@
<InternalsVisibleToTest Include="Roslyn.Services.Editor.UnitTests2" />
<InternalsVisibleToTest Include="Roslyn.Services.Editor.VisualBasic.UnitTests" />
<InternalsVisibleToTest Include="Roslyn.VisualStudio.Services.UnitTests" />
<InternalsVisibleToTest Include="Roslyn.VisualStudio.CSharp.UnitTests" />
</ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.CSharp" />
......@@ -373,4 +374,4 @@
<Import Project="..\..\..\build\Targets\VSL.Imports.targets" />
<Import Project="..\..\..\build\Targets\Roslyn.Toolsets.Xunit.targets" />
</ImportGroup>
</Project>
\ No newline at end of file
</Project>
......@@ -21,6 +21,7 @@
<ItemGroup>
<InternalsVisibleToTest Include="Roslyn.InteractiveWindow.UnitTests" />
<InternalsVisibleToTest Include="Roslyn.Services.Editor.UnitTests2" />
<InternalsVisibleToTest Include="Roslyn.VisualStudio.CSharp.UnitTests" />
<InternalsVisibleTo Include="Microsoft.VisualStudio.InteractiveServices" />
<InternalsVisibleTo Include="Microsoft.VisualStudio.VsInteractiveWindow" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.EditorFeatures" />
......@@ -149,4 +150,4 @@
<ImportGroup Label="Targets">
<Import Project="..\..\..\build\Targets\VSL.Imports.targets" />
</ImportGroup>
</Project>
\ No newline at end of file
</Project>
......@@ -19,11 +19,17 @@
<Reference Include="Microsoft.VisualStudio.Composition, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>$(DevEnvDir)\PrivateAssemblies\Microsoft.VisualStudio.Composition.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.Language.StandardClassification, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
<Reference Include="Microsoft.VisualStudio.Platform.VSEditor, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
<Reference Include="Microsoft.VisualStudio.Shell.Interop.14.0.DesignTime, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<EmbedInteropTypes>True</EmbedInteropTypes>
</Reference>
</ItemGroup>
<ItemGroup Label="Project References">
<ProjectReference Include="..\..\..\Interactive\EditorFeatures\Core\InteractiveEditorFeatures.csproj">
<Project>{92412d1a-0f23-45b5-b196-58839c524917}</Project>
<Name>InteractiveEditorFeatures</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\Test\Utilities\Portable.FX45\TestUtilities.FX45.csproj">
<Project>{f7712928-1175-47b3-8819-ee086753dee2}</Project>
<Name>TestUtilities.FX45</Name>
......@@ -147,6 +153,7 @@
<Reference Include="Microsoft.VisualStudio.Text.Data, Version=$(VisualStudioReferenceAssemblyVersion), Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<Private>false</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.Text.Internal, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
<Reference Include="Microsoft.VisualStudio.Text.Logic, Version=$(VisualStudioReferenceAssemblyVersion), Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<Private>false</Private>
</Reference>
......@@ -187,6 +194,14 @@
<Compile Include="Debugging\DataTipInfoGetterTests.cs" />
<Compile Include="Debugging\LocationInfoGetterTests.cs" />
<Compile Include="Debugging\NameResolverTests.cs" />
<Compile Include="Interactive\Commands\InteractiveCommandHandlerTests.cs" />
<Compile Include="Interactive\Commands\TestInteractiveCommandHandler.cs" />
<Compile Include="Interactive\Commands\InteractiveWindowCommandHandlerTestState.cs" />
<Compile Include="Interactive\InteractiveWindowEditorsFactoryService.cs" />
<Compile Include="Interactive\InteractiveWindowTestHost.cs" />
<Compile Include="Interactive\Commands\ResetInteractiveTests.cs" />
<Compile Include="Interactive\Commands\TestResetInteractive.cs" />
<Compile Include="Interactive\TestInteractiveEvaluator.cs" />
<Compile Include="PersistentStorage\SolutionSizeTests.cs" />
<Compile Include="ProjectSystemShim\CSharpReferencesTests.cs" />
<Compile Include="ProjectSystemShim\SourceFileHandlingTests.cs" />
......@@ -226,4 +241,4 @@
<Import Project="..\..\..\..\build\Targets\VSL.Imports.targets" />
<Import Project="..\..\..\..\build\Targets\Roslyn.Toolsets.Xunit.targets" />
</ImportGroup>
</Project>
</Project>
\ 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;
using System.Collections.Generic;
using Xunit;
using Roslyn.Test.Utilities;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Interactive.Commands
{
internal class InteractiveCommandHandlerTests
{
private const string ExampleCode1 =
@"var x = 1;
Task.Run(() => { return 1; });";
[WpfFact]
[Trait(Traits.Feature, Traits.Features.Interactive)]
public void TestExecuteInInteractiveWithoutSelection()
{
AssertUnavailableExecuteInInteractive("$$");
AssertUnavailableExecuteInInteractive($"{ExampleCode1}$$");
}
[WpfFact]
[Trait(Traits.Feature, Traits.Features.Interactive)]
public void TestExecuteInInteractiveWithEmptyBuffer()
{
AssertExecuteInInteractive(@"{|Selection:var x = 1;$$|}", "var x = 1;");
AssertExecuteInInteractive($@"{{|Selection:{ExampleCode1}$$|}}", ExampleCode1);
AssertExecuteInInteractive(
$@"var o = new object[] {{ 1, 2, 3 }};
Console.WriteLine(o);
{{|Selection:{ExampleCode1}$$|}}
Console.WriteLine(x);", ExampleCode1);
}
[WpfFact]
[Trait(Traits.Feature, Traits.Features.Interactive)]
public void TestExecuteInInteractiveWithBoxSelection()
{
string expectedBoxSubmissionResult = @"int x;
int y;";
AssertExecuteInInteractive(
$@"some text {{|Selection:$$int x;|}} also here
text some {{|Selection:int y;|}} here also", expectedBoxSubmissionResult);
AssertExecuteInInteractive(
$@"some text {{|Selection:int x;$$|}} also here
text some {{|Selection:int y;|}} here also", expectedBoxSubmissionResult);
AssertExecuteInInteractive(
$@"some text {{|Selection:int x;|}} also here
text some {{|Selection:$$int y;|}} here also", expectedBoxSubmissionResult);
AssertExecuteInInteractive(
$@"some text {{|Selection:int x;|}} also here
text some {{|Selection:int y;$$|}} here also", expectedBoxSubmissionResult);
}
[WpfFact]
[Trait(Traits.Feature, Traits.Features.Interactive)]
public void TestExecuteInInteractiveWithNonEmptyBuffer()
{
// Execute in interactive clears the existing current buffer before execution.
// Therefore `var x = 1;` will not be executed.
AssertExecuteInInteractive(
@"{|Selection:var y = 2;$$|}",
"var y = 2;",
submissionBuffer: "var x = 1;");
}
[WpfFact]
[Trait(Traits.Feature, Traits.Features.Interactive)]
public void TestCopyToInteractiveWithoutSelection()
{
AssertUnavailableCopyToInteractive("$$");
AssertUnavailableCopyToInteractive($"{ExampleCode1}$$");
AssertUnavailableCopyToInteractive($"{ExampleCode1}$$", submissionBuffer: "var x = 1;");
AssertUnavailableCopyToInteractive($"{ExampleCode1}$$", submissionBuffer: "x = 2;");
}
[WpfFact]
[Trait(Traits.Feature, Traits.Features.Interactive)]
public void TestCopyToInteractive()
{
AssertCopyToInteractive($"{{|Selection:{ExampleCode1}$$|}}", ExampleCode1);
}
[WpfFact]
[Trait(Traits.Feature, Traits.Features.Interactive)]
public void TestCopyToInteractiveWithNonEmptyBuffer()
{
// Copy to interactive does not clear the existing buffer.
// Therefore `var x = 1;` will still be present in the final buffer.
AssertCopyToInteractive(
$"{{|Selection:{ExampleCode1}$$|}}",
$"var x = 1;\r\n{ExampleCode1}",
submissionBuffer: "var x = 1;");
}
private static void AssertUnavailableCopyToInteractive(string code, string submissionBuffer = null)
{
using (var workspace = InteractiveWindowCommandHandlerTestState.CreateTestState(code))
{
PrepareSubmissionBuffer(submissionBuffer, workspace);
Assert.Equal(CommandState.Unavailable, workspace.GetStateForCopyToInteractive());
}
}
private static void AssertCopyToInteractive(string code, string expectedBufferText, string submissionBuffer = null)
{
using (var workspace = InteractiveWindowCommandHandlerTestState.CreateTestState(code))
{
PrepareSubmissionBuffer(submissionBuffer, workspace);
workspace.SendCopyToInteractive();
Assert.Equal(expectedBufferText, workspace.WindowCurrentLanguageBuffer.CurrentSnapshot.GetText());
}
}
private static void AssertUnavailableExecuteInInteractive(string code)
{
using (var workspace = InteractiveWindowCommandHandlerTestState.CreateTestState(code))
{
Assert.Equal(CommandState.Unavailable, workspace.GetStateForExecuteInInteractive());
}
}
private static void AssertExecuteInInteractive(string code, string expectedSubmission, string submissionBuffer = null)
{
List<string> submissions = new List<string>();
EventHandler<string> appendSubmission = (_, item) => { submissions.Add(item.TrimEnd()); };
using (var workspace = InteractiveWindowCommandHandlerTestState.CreateTestState(code))
{
PrepareSubmissionBuffer(submissionBuffer, workspace);
Assert.Equal(CommandState.Available, workspace.GetStateForExecuteInInteractive());
workspace.Evaluator.OnExecute += appendSubmission;
workspace.ExecuteInInteractive();
AssertEx.Equal(new string[] { expectedSubmission }, submissions);
}
}
private static void PrepareSubmissionBuffer(string submissionBuffer, InteractiveWindowCommandHandlerTestState workspace)
{
if (string.IsNullOrEmpty(submissionBuffer))
{
return;
}
workspace.WindowCurrentLanguageBuffer.Insert(0, submissionBuffer);
}
}
}
// 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.CodeAnalysis.Editor.Commands;
using Microsoft.CodeAnalysis.Editor.Interactive;
using Microsoft.CodeAnalysis.Editor.UnitTests;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.Text.Operations;
using Microsoft.VisualStudio.Utilities;
using System.Xml.Linq;
using Microsoft.VisualStudio.Text;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Interactive.Commands
{
/// <summary>
/// This class creates a mock execution state that allows to send CopyToInteractive and ExeciteInInteractive.
/// Commands against a mock InteractiveWindow.
/// </summary>
internal class InteractiveWindowCommandHandlerTestState : AbstractCommandHandlerTestState
{
public InteractiveWindowTestHost TestHost { get; }
private InteractiveCommandHandler _commandHandler;
public ITextView WindowTextView => TestHost.Window.TextView;
public ITextBuffer WindowCurrentLanguageBuffer => TestHost.Window.CurrentLanguageBuffer;
public ITextSnapshot WindowSnapshot => WindowCurrentLanguageBuffer.CurrentSnapshot;
public TestInteractiveEvaluator Evaluator => TestHost.Evaluator;
private ICommandHandler<ExecuteInInteractiveCommandArgs> ExecuteInInteractiveCommandHandler => _commandHandler;
private ICommandHandler<CopyToInteractiveCommandArgs> CopyToInteractiveCommandHandler => _commandHandler;
public InteractiveWindowCommandHandlerTestState(XElement workspaceElement)
: base(workspaceElement)
{
TestHost = new InteractiveWindowTestHost();
_commandHandler = new TestInteractiveCommandHandler(
TestHost.Window,
GetExportedValue<IContentTypeRegistryService>(),
GetExportedValue<IEditorOptionsFactoryService>(),
GetExportedValue<IEditorOperationsFactoryService>());
}
public static InteractiveWindowCommandHandlerTestState CreateTestState(string markup)
{
var workspaceXml = XElement.Parse($@"
<Workspace>
<Project Language=""C#"" CommonReferences=""true"">
<Document>{markup}</Document>
</Project>
</Workspace>
");
return new InteractiveWindowCommandHandlerTestState(workspaceXml);
}
public void SendCopyToInteractive()
{
var copyToInteractiveArgs = new CopyToInteractiveCommandArgs(TextView, SubjectBuffer);
CopyToInteractiveCommandHandler.ExecuteCommand(copyToInteractiveArgs, () => { });
}
public CommandState GetStateForCopyToInteractive()
{
var copyToInteractiveArgs = new CopyToInteractiveCommandArgs(TextView, SubjectBuffer);
return CopyToInteractiveCommandHandler.GetCommandState(
copyToInteractiveArgs, () => { return CommandState.Unavailable; });
}
public void ExecuteInInteractive()
{
var executeInInteractiveArgs = new ExecuteInInteractiveCommandArgs(TextView, SubjectBuffer);
ExecuteInInteractiveCommandHandler.ExecuteCommand(executeInInteractiveArgs, () => { });
}
public CommandState GetStateForExecuteInInteractive()
{
var executeInInteractiveArgs = new ExecuteInInteractiveCommandArgs(TextView, SubjectBuffer);
return ExecuteInInteractiveCommandHandler.GetCommandState(
executeInInteractiveArgs, () => { return CommandState.Unavailable; });
}
}
}
// 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 Roslyn.Test.Utilities;
using Xunit;
using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces;
using Microsoft.CodeAnalysis.Editor.Host;
using System.Collections.Generic;
using System;
using System.Collections.Immutable;
using System.Linq;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Interactive.Commands
{
public class ResetInteractiveTests
{
private string WorkspaceXmlStr =>
@"<Workspace>
<Project Language=""Visual Basic"" AssemblyName=""ResetInteractiveVisualBasicSubproject"" CommonReferences=""true"">
<Document FilePath=""VisualBasicDocument""></Document>
</Project>
<Project Language=""C#"" AssemblyName=""ResetInteractiveTestsAssembly"" CommonReferences=""true"">
<ProjectReference>ResetInteractiveVisualBasicSubproject</ProjectReference>
<Document FilePath=""ResetInteractiveTestsDocument""></Document>
</Project>
</Workspace>";
[WpfFact]
[Trait(Traits.Feature, Traits.Features.Interactive)]
public async void TestResetREPLWithProjectContext()
{
using (var workspace = await TestWorkspace.CreateAsync(WorkspaceXmlStr))
{
var project = workspace.CurrentSolution.Projects.FirstOrDefault(p => p.AssemblyName == "ResetInteractiveTestsAssembly");
var document = project.Documents.FirstOrDefault(d => d.FilePath == "ResetInteractiveTestsDocument");
var replReferenceCommands = GetProjectReferences(workspace, project).Select(r => CreateReplReferenceCommand(r));
Assert.True(replReferenceCommands.Any(rc => rc.EndsWith(@"ResetInteractiveTestsAssembly.dll""")));
Assert.True(replReferenceCommands.Any(rc => rc.EndsWith(@"ResetInteractiveVisualBasicSubproject.dll""")));
var expectedSubmissions = new List<string> {
string.Join("\r\n", replReferenceCommands) + "\r\n",
string.Join("\r\n", @"using ""ns1"";", @"using ""ns2"";") + "\r\n"};
AssertResetInteractive(workspace, project, buildSucceeds: true, expectedSubmissions: expectedSubmissions);
// Test that no submissions are executed if the build fails.
AssertResetInteractive(workspace, project, buildSucceeds: false, expectedSubmissions: new List<string>());
}
}
private async void AssertResetInteractive(
TestWorkspace workspace,
Project project,
bool buildSucceeds,
List<string> expectedSubmissions)
{
InteractiveWindowTestHost testHost = new InteractiveWindowTestHost();
List<string> executedSubmissionCalls = new List<string>();
EventHandler<string> ExecuteSubmission = (_, code) => { executedSubmissionCalls.Add(code); };
testHost.Evaluator.OnExecute += ExecuteSubmission;
IWaitIndicator waitIndicator = workspace.GetService<IWaitIndicator>();
TestResetInteractive resetInteractive = new TestResetInteractive(
waitIndicator,
CreateReplReferenceCommand,
CreateImport,
buildSucceeds: buildSucceeds)
{
References = ImmutableArray.CreateRange(GetProjectReferences(workspace, project)),
ReferenceSearchPaths = ImmutableArray.Create("rsp1", "rsp2"),
SourceSearchPaths = ImmutableArray.Create("ssp1", "ssp2"),
NamespacesToImport = ImmutableArray.Create("ns1", "ns2"),
ProjectDirectory = "pj",
};
await resetInteractive.Execute(testHost.Window, "Interactive C#");
// Validate that the project was rebuilt.
Assert.Equal(1, resetInteractive.BuildProjectCount);
Assert.Equal(0, resetInteractive.CancelBuildProjectCount);
AssertEx.Equal(expectedSubmissions, executedSubmissionCalls);
testHost.Evaluator.OnExecute -= ExecuteSubmission;
}
/// <summary>
/// Simulates getting all project references.
/// </summary>
/// <param name="workspace">Workspace with the solution.</param>
/// <param name="project">A project that should be built.</param>
/// <returns>A list of paths that should be referenced.</returns>
private IEnumerable<string> GetProjectReferences(TestWorkspace workspace, Project project)
{
var metadataReferences = project.MetadataReferences.Select(r => r.Display);
var projectReferences = project.ProjectReferences.SelectMany(p => GetProjectReferences(
workspace,
workspace.CurrentSolution.GetProject(p.ProjectId)));
var outputReference = new string[] { project.OutputFilePath };
return metadataReferences.Union(projectReferences).Concat(outputReference);
}
private string CreateReplReferenceCommand(string referenceName)
{
return $@"#r ""{referenceName}""";
}
private string CreateImport(string importName)
{
return $@"using ""{importName}"";";
}
}
}
// 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.CodeAnalysis.Editor.Interactive;
using Microsoft.VisualStudio.InteractiveWindow;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.Text.Operations;
using Microsoft.VisualStudio.Utilities;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Interactive.Commands
{
internal class TestInteractiveCommandHandler : InteractiveCommandHandler
{
private IInteractiveWindow _interactiveWindow;
public TestInteractiveCommandHandler(
IInteractiveWindow interactiveWindow,
IContentTypeRegistryService contentTypeRegistryService,
IEditorOptionsFactoryService editorOptionsFactoryService,
IEditorOperationsFactoryService editorOperationsFactoryService)
: base(contentTypeRegistryService, editorOptionsFactoryService, editorOperationsFactoryService)
{
_interactiveWindow = interactiveWindow;
}
protected override IInteractiveWindow OpenInteractiveWindow(bool focus)
{
return _interactiveWindow;
}
}
}
// 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.CodeAnalysis.Editor.Host;
using Microsoft.VisualStudio.LanguageServices.Interactive;
using System;
using System.Collections.Immutable;
using System.Threading.Tasks;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Interactive.Commands
{
internal class TestResetInteractive : ResetInteractive
{
private IWaitIndicator _waitIndicator;
private bool _buildSucceeds;
internal int BuildProjectCount { get; private set; }
internal int CancelBuildProjectCount { get; private set; }
internal ImmutableArray<string> References { get; set; }
internal ImmutableArray<string> ReferenceSearchPaths { get; set; }
internal ImmutableArray<string> SourceSearchPaths { get; set; }
internal ImmutableArray<string> NamespacesToImport { get; set; }
internal string ProjectDirectory { get; set; }
public TestResetInteractive(IWaitIndicator waitIndicator, Func<string, string> createReference, Func<string, string> createImport, bool buildSucceeds)
: base(createReference, createImport)
{
_waitIndicator = waitIndicator;
_buildSucceeds = buildSucceeds;
}
protected override void CancelBuildProject()
{
CancelBuildProjectCount++;
}
protected override Task<bool> BuildProject()
{
BuildProjectCount++;
return Task.FromResult(_buildSucceeds);
}
protected override bool GetProjectProperties(
out ImmutableArray<string> references,
out ImmutableArray<string> referenceSearchPaths,
out ImmutableArray<string> sourceSearchPaths,
out ImmutableArray<string> namespacesToImport,
out string projectDirectory)
{
references = References;
referenceSearchPaths = ReferenceSearchPaths;
sourceSearchPaths = SourceSearchPaths;
namespacesToImport = NamespacesToImport;
projectDirectory = ProjectDirectory;
return true;
}
protected override IWaitIndicator GetWaitIndicator()
{
return _waitIndicator;
}
}
}
// 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.ComponentModel.Composition;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.Utilities;
using Roslyn.Test.Utilities;
using Microsoft.VisualStudio.InteractiveWindow;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Interactive
{
[Export(typeof(IInteractiveWindowEditorFactoryService))]
internal class InteractiveWindowEditorsFactoryService : IInteractiveWindowEditorFactoryService
{
public const string ContentType = "text";
private readonly ITextBufferFactoryService _textBufferFactoryService;
private readonly ITextEditorFactoryService _textEditorFactoryService;
private readonly IContentTypeRegistryService _contentTypeRegistry;
[ImportingConstructor]
public InteractiveWindowEditorsFactoryService(ITextBufferFactoryService textBufferFactoryService, ITextEditorFactoryService textEditorFactoryService, IContentTypeRegistryService contentTypeRegistry)
{
_textBufferFactoryService = textBufferFactoryService;
_textEditorFactoryService = textEditorFactoryService;
_contentTypeRegistry = contentTypeRegistry;
}
IWpfTextView IInteractiveWindowEditorFactoryService.CreateTextView(IInteractiveWindow window, ITextBuffer buffer, ITextViewRoleSet roles)
{
WpfTestCase.RequireWpfFact($"Creates an IWpfTextView in {nameof(InteractiveWindowEditorsFactoryService)}");
var textView = _textEditorFactoryService.CreateTextView(buffer, roles);
return _textEditorFactoryService.CreateTextViewHost(textView, false).TextView;
}
ITextBuffer IInteractiveWindowEditorFactoryService.CreateAndActivateBuffer(IInteractiveWindow window)
{
IContentType contentType;
if (!window.Properties.TryGetProperty(typeof(IContentType), out contentType))
{
contentType = _contentTypeRegistry.GetContentType(ContentType);
}
return _textBufferFactoryService.CreateTextBuffer(contentType);
}
}
}
// 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.ComponentModel.Composition.Hosting;
using System.Linq;
using Microsoft.VisualStudio.Utilities;
using Microsoft.VisualStudio.InteractiveWindow;
using Microsoft.CodeAnalysis.Editor.UnitTests.Utilities;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Interactive
{
public sealed class InteractiveWindowTestHost : IDisposable
{
internal readonly IInteractiveWindow Window;
internal readonly TestInteractiveEvaluator Evaluator;
private readonly CompositionContainer ExportProvider;
private static readonly Lazy<AggregateCatalog> _lazyCatalog = new Lazy<AggregateCatalog>(() =>
{
var types = new[] { typeof(TestWaitIndicator), typeof(TestInteractiveEvaluator), typeof(InteractiveWindow) }.Concat(GetVisualStudioTypes());
return new AggregateCatalog(types.Select(t => new AssemblyCatalog(t.Assembly)));
});
internal InteractiveWindowTestHost(Action<InteractiveWindow.State> stateChangedHandler = null)
{
ExportProvider = new CompositionContainer(
_lazyCatalog.Value,
CompositionOptions.DisableSilentRejection | CompositionOptions.IsThreadSafe);
var contentTypeRegistryService = ExportProvider.GetExport<IContentTypeRegistryService>().Value;
Evaluator = new TestInteractiveEvaluator();
Window = ExportProvider.GetExport<IInteractiveWindowFactoryService>().Value.CreateWindow(Evaluator);
((InteractiveWindow)Window).StateChanged += stateChangedHandler;
Window.InitializeAsync().Wait();
}
private static Type[] GetVisualStudioTypes()
{
var types = new[]
{
// EDITOR
// Microsoft.VisualStudio.Platform.VSEditor.dll:
typeof(VisualStudio.Platform.VSEditor.EventArgsHelper),
// Microsoft.VisualStudio.Text.Logic.dll:
// Must include this because several editor options are actually stored as exported information
// on this DLL. Including most importantly, the tab size information.
typeof(VisualStudio.Text.Editor.DefaultOptions),
// Microsoft.VisualStudio.Text.UI.dll:
// Include this DLL to get several more EditorOptions including WordWrapStyle.
typeof(VisualStudio.Text.Editor.WordWrapStyle),
// Microsoft.VisualStudio.Text.UI.Wpf.dll:
// Include this DLL to get more EditorOptions values.
typeof(VisualStudio.Text.Editor.HighlightCurrentLineOption),
// BasicUndo.dll:
// Include this DLL to satisfy ITextUndoHistoryRegistry
typeof(BasicUndo.IBasicUndoHistory),
// Microsoft.VisualStudio.Language.StandardClassification.dll:
typeof(VisualStudio.Language.StandardClassification.PredefinedClassificationTypeNames)
};
return types;
}
public void Dispose()
{
if (Window != null)
{
// close interactive host process:
Window.Evaluator?.Dispose();
// dispose buffer:
Window.Dispose();
}
}
}
}
// 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.Threading.Tasks;
using Microsoft.VisualStudio.InteractiveWindow;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Interactive
{
internal sealed class TestInteractiveEvaluator : IInteractiveEvaluator
{
internal event EventHandler<string> OnExecute;
public IInteractiveWindow CurrentWindow { get; set; }
public void Dispose()
{
}
public Task<ExecutionResult> InitializeAsync()
{
return Task.FromResult(ExecutionResult.Success);
}
public Task<ExecutionResult> ResetAsync(bool initialize = true)
{
return Task.FromResult(ExecutionResult.Success);
}
public bool CanExecuteCode(string text)
{
return true;
}
public Task<ExecutionResult> ExecuteCodeAsync(string text)
{
OnExecute?.Invoke(this, text);
return Task.FromResult(ExecutionResult.Success);
}
public string FormatClipboard()
{
return null;
}
public void AbortExecution()
{
}
public string GetConfiguration()
{
return "config";
}
public string GetPrompt()
{
return "> ";
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册