Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable async completion #33795

Merged
merged 11 commits into from Mar 3, 2019
18 changes: 13 additions & 5 deletions azure-pipelines-integration.yml
Expand Up @@ -22,16 +22,24 @@ jobs:
- job: Windows_VisualStudio_Integration_Tests
pool: dotnet-external-vs2019-preview
strategy:
maxParallel: 2
maxParallel: 4
matrix:
debug:
_configuration: Debug
_useLegacyCompletion: false
release:
_configuration: Release
_useLegacyCompletion: false
debug_legacy:
_configuration: Debug
_useLegacyCompletion: true
release_legacy:
_configuration: Release
_useLegacyCompletion: true
timeoutInMinutes: 135

steps:
- script: eng/cibuild.cmd -configuration $(_configuration) -prepareMachine -testVsi
- script: eng/cibuild.cmd -configuration $(_configuration) -prepareMachine -testVsi -testLegacyCompletion:$$(_useLegacyCompletion)
displayName: Build and Test

- task: PublishTestResults@1
Expand All @@ -40,14 +48,14 @@ jobs:
testRunner: XUnit
testResultsFiles: $(Build.SourcesDirectory)\artifacts\TestResults\$(_configuration)\*.xml
mergeTestResults: true
testRunTitle: 'Windows Visual Studio Integration $(_configuration)'
testRunTitle: 'Windows Visual Studio Integration $(_configuration)_$(_useLegacyCompletion)'
condition: always()

- task: PublishBuildArtifacts@1
displayName: Publish Logs
inputs:
PathtoPublish: '$(Build.SourcesDirectory)\artifacts\log\$(_configuration)'
ArtifactName: 'Windows Visual Studio Integration $(_configuration)'
ArtifactName: 'Windows Visual Studio Integration $(_configuration)_$(_useLegacyCompletion)'
publishLocation: Container
continueOnError: true
condition: not(succeeded())
Expand All @@ -56,7 +64,7 @@ jobs:
displayName: Publish Screenshots
inputs:
PathtoPublish: '$(Build.SourcesDirectory)\artifacts\bin\Microsoft.VisualStudio.LanguageServices.IntegrationTests\$(_configuration)\net472\xUnitResults'
ArtifactName: 'Screenshots $(_configuration)'
ArtifactName: 'Screenshots $(_configuration)_$(_useLegacyCompletion)'
publishLocation: Container
continueOnError: true
condition: not(succeeded())
9 changes: 9 additions & 0 deletions eng/build.ps1
Expand Up @@ -57,6 +57,7 @@ param (
[switch][Alias('test')]$testDesktop,
[switch]$testCoreClr,
[switch]$testIOperation,
[switch]$testLegacyCompletion,

[parameter(ValueFromRemainingArguments=$true)][string[]]$properties)

Expand Down Expand Up @@ -87,6 +88,7 @@ function Print-Usage() {
Write-Host " -testCoreClr Run CoreClr unit tests"
Write-Host " -testVsi Run all integration tests"
Write-Host " -testIOperation Run extra checks to validate IOperations"
Write-Host " -testLegacyCompletion Run integration tests with legacy completion"
Write-Host ""
Write-Host "Advanced settings:"
Write-Host " -ci Set when running on CI server"
Expand Down Expand Up @@ -325,6 +327,10 @@ function TestUsingOptimizedRunner() {
$env:ROSLYN_TEST_IOPERATION = "true"
}

if ($testLegacyCompletion) {
$env:ROSLYN_TEST_LEGACY_COMPLETION = "true"
}

$testResultsDir = Join-Path $ArtifactsDir "TestResults\$configuration"
$binDir = Join-Path $ArtifactsDir "bin"
$runTests = GetProjectOutputBinary "RunTests.exe"
Expand Down Expand Up @@ -397,6 +403,9 @@ function TestUsingOptimizedRunner() {
if ($testIOperation) {
Remove-Item env:\ROSLYN_TEST_IOPERATION
}
if ($testLegacyCompletion) {
Remove-Item env:\ROSLYN_TEST_LEGACY_COMPLETION
}
}
}

Expand Down
Expand Up @@ -162,5 +162,21 @@ private ImmutableHashSet<char> GetAllAutoBraceCompletionChars(IContentType buffe

return set;
}

internal TestAccessor GetTestAccessor()
=> new TestAccessor(this);

internal readonly struct TestAccessor
{
private readonly AsyncCompletionService _asyncCompletionService;

public TestAccessor(AsyncCompletionService asyncCompletionService)
{
_asyncCompletionService = asyncCompletionService;
}

internal bool UseLegacyCompletion(ITextView textView, ITextBuffer subjectBuffer)
=> _asyncCompletionService.UseLegacyCompletion(textView, subjectBuffer);
}
}
}
Expand Up @@ -51,7 +51,7 @@ public override async Task InitializeAsync()
_projectTemplate != WellKnownProjectTemplates.WpfApplication &&
_projectTemplate != WellKnownProjectTemplates.CSharpNetCoreClassLibrary)
{
VisualStudio.Workspace.SetUseSuggestionMode(false);
VisualStudio.Editor.SetUseSuggestionMode(false);
ClearEditor();
}
}
Expand Down
Expand Up @@ -63,6 +63,13 @@ public virtual async Task InitializeAsync()
/// </summary>
public virtual Task DisposeAsync()
{
if (VisualStudio?.Editor.IsCompletionActive() ?? false)
{
// Make sure completion isn't visible.
// 🐛 Only needed as a workaround for https://devdiv.visualstudio.com/DevDiv/_workitems/edit/801435
VisualStudio.SendKeys.Send(VirtualKey.Escape);
sharwell marked this conversation as resolved.
Show resolved Hide resolved
}

_visualStudioContext.Dispose();
return Task.CompletedTask;
}
Expand Down
@@ -1,5 +1,7 @@
// 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.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.VisualStudio.IntegrationTest.Utilities;
Expand Down Expand Up @@ -87,7 +89,7 @@ public static class NavigateTo
[WpfFact, Trait(Traits.Feature, Traits.Features.Completion)]
public void CtrlAltSpace()
{
VisualStudio.Workspace.SetUseSuggestionMode(false);
VisualStudio.Editor.SetUseSuggestionMode(false);

VisualStudio.Editor.SendKeys("nam Goo", VirtualKey.Enter);
VisualStudio.Editor.SendKeys('{', VirtualKey.Enter, '}', VirtualKey.Up, VirtualKey.Enter);
Expand All @@ -99,7 +101,7 @@ public void CtrlAltSpace()
VisualStudio.Editor.Verify.CurrentLineText("System.Console.WriteLine();$$", assertCaretPosition: true);
VisualStudio.Editor.SendKeys(VirtualKey.Home, Shift(VirtualKey.End), VirtualKey.Delete);

VisualStudio.ExecuteCommand(WellKnownCommandNames.Edit_ToggleCompletionMode);
VisualStudio.Editor.SendKeys(new KeyPress(VirtualKey.Space, ShiftState.Ctrl | ShiftState.Alt));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change is fine but just checking here -- did we break the command?

Copy link
Member Author

@sharwell sharwell Mar 5, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, the command works, and we use the command in other test contexts. This was supposed to be a test for Ctrl+Alt+Space though.


VisualStudio.Editor.SendKeys("System.Console.writeline();");
VisualStudio.Editor.Verify.CurrentLineText("System.Console.writeline();$$", assertCaretPosition: true);
Expand All @@ -108,13 +110,13 @@ public void CtrlAltSpace()
[WpfFact, Trait(Traits.Feature, Traits.Features.Completion)]
public void CtrlAltSpaceOption()
{
VisualStudio.Workspace.SetUseSuggestionMode(false);
VisualStudio.Editor.SetUseSuggestionMode(false);

VisualStudio.Editor.SendKeys("nam Goo");
VisualStudio.Editor.Verify.CurrentLineText("namespace Goo$$", assertCaretPosition: true);

ClearEditor();
VisualStudio.Workspace.SetUseSuggestionMode(true);
VisualStudio.Editor.SetUseSuggestionMode(true);

VisualStudio.Editor.SendKeys("nam Goo");
VisualStudio.Editor.Verify.CurrentLineText("nam Goo$$", assertCaretPosition: true);
Expand Down Expand Up @@ -157,6 +159,20 @@ void Main(string[] args)
VisualStudio.Editor.SendKeys("<s");
VisualStudio.Editor.Verify.CompletionItemsExist("see", "seealso", "summary");

if (LegacyCompletionCondition.Instance.ShouldSkip)
{
// 🐛 Workaround for https://github.com/dotnet/roslyn/issues/33824
var completionItems = VisualStudio.Editor.GetCompletionItems();
var targetIndex = Array.IndexOf(completionItems, "see");
var currentIndex = Array.IndexOf(completionItems, VisualStudio.Editor.GetCurrentCompletionItem());
if (currentIndex != targetIndex)
{
var key = currentIndex < targetIndex ? VirtualKey.Down : VirtualKey.Up;
var keys = Enumerable.Repeat(key, Math.Abs(currentIndex - targetIndex)).Cast<object>().ToArray();
VisualStudio.Editor.SendKeys(keys);
}
}

VisualStudio.Editor.SendKeys(VirtualKey.Enter);
VisualStudio.Editor.Verify.CurrentLineText("///<see cref=\"$$\"/>", assertCaretPosition: true);
}
Expand Down Expand Up @@ -193,15 +209,17 @@ void Main(string[] args)
}
}");

VisualStudio.Workspace.SetUseSuggestionMode(false);
VisualStudio.Editor.SetUseSuggestionMode(false);

VisualStudio.Editor.SendKeys("Mai(");

VisualStudio.Editor.Verify.CurrentSignature("void Class1.Main(string[] args)");
VisualStudio.Editor.Verify.CurrentParameter("args", "");
}

[WpfFact, Trait(Traits.Feature, Traits.Features.Completion)]
// 🐛 The async completion controller in 16.0 Preview 4 fails to account for brace completion sessions.
[ConditionalWpfFact(typeof(LegacyCompletionCondition)), Trait(Traits.Feature, Traits.Features.Completion)]
[WorkItem(33825, "https://github.com/dotnet/roslyn/issues/33825")]
public void CompletionUsesTrackingPointsInTheFaceOfAutomaticBraceCompletion()
{
SetUpEditor(@"
Expand All @@ -211,7 +229,7 @@ void Main(string[] args)
$$
}");

VisualStudio.Workspace.SetUseSuggestionMode(false);
VisualStudio.Editor.SetUseSuggestionMode(false);

VisualStudio.Editor.SendKeys(
'{',
Expand All @@ -232,7 +250,9 @@ void Main(string[] args)
assertCaretPosition: true);
}

[WpfFact, Trait(Traits.Feature, Traits.Features.Completion)]
// 🐛 This should work with async completion, but currently does not.
[ConditionalWpfFact(typeof(LegacyCompletionCondition)), Trait(Traits.Feature, Traits.Features.Completion)]
[WorkItem(33823, "https://github.com/dotnet/roslyn/issues/33823")]
public void CommitOnShiftEnter()
{
SetUpEditor(@"
Expand All @@ -244,7 +264,7 @@ void Main(string[] args)
}
}");

VisualStudio.Workspace.SetUseSuggestionMode(false);
VisualStudio.Editor.SetUseSuggestionMode(false);

VisualStudio.Editor.SendKeys(
'M',
Expand All @@ -261,6 +281,36 @@ void Main(string[] args)
assertCaretPosition: true);
}

[WpfFact, Trait(Traits.Feature, Traits.Features.Completion)]
public void LineBreakOnShiftEnter()
{
SetUpEditor(@"
class Class1
{
void Main(string[] args)
{
$$
}
}");

VisualStudio.Editor.SetUseSuggestionMode(true);

VisualStudio.Editor.SendKeys(
'M',
Shift(VirtualKey.Enter));

VisualStudio.Editor.Verify.TextContains(@"
class Class1
{
void Main(string[] args)
{
M
$$
}
}",
assertCaretPosition: true);
}

[WpfFact, Trait(Traits.Feature, Traits.Features.Completion)]
public void CommitOnLeftCurly()
{
Expand All @@ -270,7 +320,7 @@ class Class1
$$
}");

VisualStudio.Workspace.SetUseSuggestionMode(false);
VisualStudio.Editor.SetUseSuggestionMode(false);

VisualStudio.Editor.SendKeys("int P { g{");

Expand All @@ -282,26 +332,31 @@ class Class1
assertCaretPosition: true);
}

[WpfFact, Trait(Traits.Feature, Traits.Features.Completion)]
[ConditionalWpfFact(typeof(LegacyCompletionCondition)), Trait(Traits.Feature, Traits.Features.Completion)]
[WorkItem(33822, "https://github.com/dotnet/roslyn/issues/33822")]
public void EnsureTheCaretIsVisibleAfterALongEdit()
{
SetUpEditor(@"
var visibleColumns = VisualStudio.Editor.GetVisibleColumnCount();
var variableName = new string('a', (int)(0.75 * visibleColumns));
sharwell marked this conversation as resolved.
Show resolved Hide resolved
SetUpEditor($@"
public class Program
{
{{
static void Main(string[] args)
{
var aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = 0;
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = $$
}
}");
{{
var {variableName} = 0;
{variableName} = $$
}}
}}");

Assert.True(variableName.Length > 0);
VisualStudio.Editor.SendKeys(
VirtualKey.Delete,
"aaa",
VirtualKey.Tab);
var actualText = VisualStudio.Editor.GetText();
Assert.Contains("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", actualText);
Assert.Contains($"{variableName} = {variableName}", actualText);
Assert.True(VisualStudio.Editor.IsCaretOnScreen());
Assert.True(VisualStudio.Editor.GetCaretColumn() > visibleColumns, "This test is inconclusive if the view didn't need to move to keep the caret on screen.");
}

[WpfFact, Trait(Traits.Feature, Traits.Features.Completion)]
Expand Down
Expand Up @@ -97,7 +97,6 @@ public async Task WpfInteractionAsync()
[WpfFact]
public void TypingHelpDirectiveWorks()
{
VisualStudio.Workspace.SetUseSuggestionMode(true);
VisualStudio.InteractiveWindow.ShowWindow(waitForPrompt: true);

// Directly type #help, rather than sending it through VisualStudio.InteractiveWindow.SubmitText. We want to actually test
Expand Down
Expand Up @@ -18,7 +18,6 @@ public CSharpInteractiveDirectives(VisualStudioInstanceFactory instanceFactory)
[WpfFact]
public void VerifyHostCommandsCompletionList()
{
VisualStudio.Workspace.SetUseSuggestionMode(true);
VisualStudio.InteractiveWindow.InsertCode("#");
VisualStudio.InteractiveWindow.InvokeCompletionList();

Expand Down
Expand Up @@ -16,15 +16,9 @@ public CSharpReplIdeFeatures(VisualStudioInstanceFactory instanceFactory)
{
}

public override async Task InitializeAsync()
{
await base.InitializeAsync().ConfigureAwait(true);
VisualStudio.Workspace.SetUseSuggestionMode(true);
}

public override Task DisposeAsync()
{
VisualStudio.Workspace.SetUseSuggestionMode(false);
VisualStudio.Editor.SetUseSuggestionMode(false);
VisualStudio.InteractiveWindow.ClearReplText();
VisualStudio.InteractiveWindow.Reset();
return base.DisposeAsync();
Expand Down