提交 eb33645c 编写于 作者: C CyrusNajmabadi

Share more completion test code between C# and VB.

上级 7a382026
// 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.Immutable;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Completion;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Completion;
using Microsoft.CodeAnalysis.Editor.Implementation.IntelliSense.Completion;
using Microsoft.CodeAnalysis.Editor.UnitTests.Completion;
using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces;
using Microsoft.CodeAnalysis.Text;
using Xunit;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.CompletionProviders
......@@ -21,96 +18,63 @@ protected AbstractCSharpCompletionProviderTests(CSharpTestWorkspaceFixture works
{
}
protected override Task<TestWorkspace> CreateWorkspaceAsync(string fileContents)
{
return TestWorkspace.CreateCSharpAsync(fileContents);
}
internal override CompletionServiceWithProviders CreateCompletionService(
Workspace workspace, ImmutableArray<CompletionProvider> exclusiveProviders)
{
return new CSharpCompletionService(workspace, exclusiveProviders);
}
protected override async Task VerifyWorkerAsync(string code, int position, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger, bool checkForAbsence, bool experimental, int? glyph)
protected override Task BaseVerifyWorkerAsync(string code, int position, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger, bool checkForAbsence, int? glyph)
{
return base.VerifyWorkerAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, glyph: glyph);
}
protected override async Task VerifyWorkerAsync(
string code, int position,
string expectedItemOrNull, string expectedDescriptionOrNull,
SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger,
bool checkForAbsence, int? glyph)
{
await VerifyAtPositionAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, experimental, glyph);
await VerifyInFrontOfCommentAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, experimental, glyph);
await VerifyAtEndOfFileAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, experimental, glyph);
await VerifyAtPositionAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph);
await VerifyInFrontOfCommentAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph);
await VerifyAtEndOfFileAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph);
// Items cannot be partially written if we're checking for their absence,
// or if we're verifying that the list will show up (without specifying an actual item)
if (!checkForAbsence && expectedItemOrNull != null)
{
await VerifyAtPosition_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, experimental, glyph);
await VerifyInFrontOfComment_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, experimental, glyph);
await VerifyAtEndOfFile_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, experimental, glyph);
await VerifyAtPosition_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph);
await VerifyInFrontOfComment_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph);
await VerifyAtEndOfFile_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph);
}
}
protected Task BaseVerifyWorkerAsync(string code, int position, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger, bool checkForAbsence, int? glyph)
protected override string ItemPartiallyWritten(string expectedItemOrNull)
{
return base.VerifyWorkerAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, experimental: false, glyph: glyph);
return expectedItemOrNull[0] == '@' ? expectedItemOrNull.Substring(1, 1) : expectedItemOrNull.Substring(0, 1);
}
private Task VerifyInFrontOfCommentAsync(string code, int position, string insertText, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, bool experimental, int? glyph)
private Task VerifyInFrontOfCommentAsync(string code, int position, string insertText, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, int? glyph)
{
code = code.Substring(0, position) + insertText + "/**/" + code.Substring(position);
position += insertText.Length;
return base.VerifyWorkerAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, experimental, glyph: glyph);
return base.VerifyWorkerAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, glyph: glyph);
}
private Task VerifyInFrontOfCommentAsync(string code, int position, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, bool experimental, int? glyph)
private Task VerifyInFrontOfCommentAsync(string code, int position, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, int? glyph)
{
return VerifyInFrontOfCommentAsync(code, position, string.Empty, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, experimental, glyph: glyph);
return VerifyInFrontOfCommentAsync(code, position, string.Empty, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph: glyph);
}
protected Task VerifyInFrontOfComment_ItemPartiallyWrittenAsync(string code, int position, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, bool experimental, int? glyph)
protected Task VerifyInFrontOfComment_ItemPartiallyWrittenAsync(string code, int position, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, int? glyph)
{
return VerifyInFrontOfCommentAsync(code, position, ItemPartiallyWritten(expectedItemOrNull), usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, experimental, glyph: glyph);
}
protected Task VerifyAtPositionAsync(string code, int position, string insertText, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, bool experimental, int? glyph)
{
code = code.Substring(0, position) + insertText + code.Substring(position);
position += insertText.Length;
return base.VerifyWorkerAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, experimental, glyph: glyph);
}
protected Task VerifyAtPositionAsync(string code, int position, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, bool experimental, int? glyph)
{
return VerifyAtPositionAsync(code, position, string.Empty, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, experimental, glyph);
}
protected Task VerifyAtPosition_ItemPartiallyWrittenAsync(string code, int position, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, bool experimental, int? glyph)
{
return VerifyAtPositionAsync(code, position, ItemPartiallyWritten(expectedItemOrNull), usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, experimental, glyph);
}
private async Task VerifyAtEndOfFileAsync(string code, int position, string insertText, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, bool experimental, int? glyph)
{
// only do this if the placeholder was at the end of the text.
if (code.Length != position)
{
return;
}
code = code.Substring(startIndex: 0, length: position) + insertText;
position += insertText.Length;
await base.VerifyWorkerAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, experimental, glyph);
}
protected Task VerifyAtEndOfFileAsync(string code, int position, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, bool experimental, int? glyph)
{
return VerifyAtEndOfFileAsync(code, position, string.Empty, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, experimental, glyph);
}
protected Task VerifyAtEndOfFile_ItemPartiallyWrittenAsync(string code, int position, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, bool experimental, int? glyph)
{
return VerifyAtEndOfFileAsync(code, position, ItemPartiallyWritten(expectedItemOrNull), usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, experimental, glyph);
}
private static string ItemPartiallyWritten(string expectedItemOrNull)
{
return expectedItemOrNull[0] == '@' ? expectedItemOrNull.Substring(1, 1) : expectedItemOrNull.Substring(0, 1);
return VerifyInFrontOfCommentAsync(code, position, ItemPartiallyWritten(expectedItemOrNull), usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph: glyph);
}
protected string AddInsideMethod(string text)
......@@ -136,7 +100,8 @@ protected string AddUsingDirectives(string usingDirectives, string text)
text;
}
protected async Task VerifySendEnterThroughToEnterAsync(string initialMarkup, string textTypedSoFar, bool sendThroughEnterEnabled, bool expected)
protected async Task VerifySendEnterThroughToEditorAsync(
string initialMarkup, string textTypedSoFar, bool sendThroughEnterEnabled, bool expected)
{
using (var workspace = await TestWorkspace.CreateCSharpAsync(initialMarkup))
{
......@@ -156,78 +121,6 @@ protected async Task VerifySendEnterThroughToEnterAsync(string initialMarkup, st
}
}
protected async Task VerifyTextualTriggerCharacterAsync(string markup, bool shouldTriggerWithTriggerOnLettersEnabled, bool shouldTriggerWithTriggerOnLettersDisabled)
{
await VerifyTextualTriggerCharacterWorkerAsync(markup, expectedTriggerCharacter: shouldTriggerWithTriggerOnLettersEnabled, triggerOnLetter: true);
await VerifyTextualTriggerCharacterWorkerAsync(markup, expectedTriggerCharacter: shouldTriggerWithTriggerOnLettersDisabled, triggerOnLetter: false);
}
private async Task VerifyTextualTriggerCharacterWorkerAsync(string markup, bool expectedTriggerCharacter, bool triggerOnLetter)
{
using (var workspace = await TestWorkspace.CreateCSharpAsync(markup))
{
var document = workspace.Documents.Single();
var position = document.CursorPosition.Value;
var text = document.TextBuffer.CurrentSnapshot.AsText();
var options = workspace.Options.WithChangedOption(CompletionOptions.TriggerOnTypingLetters, LanguageNames.CSharp, triggerOnLetter);
var trigger = CompletionTrigger.CreateInsertionTrigger(text[position]);
var service = GetCompletionService(workspace);
var isTextualTriggerCharacterResult = service.ShouldTriggerCompletion(text, position + 1, trigger, options: options);
if (expectedTriggerCharacter)
{
var assertText = "'" + text.ToString(new Microsoft.CodeAnalysis.Text.TextSpan(position, 1)) + "' expected to be textual trigger character";
Assert.True(isTextualTriggerCharacterResult, assertText);
}
else
{
var assertText = "'" + text.ToString(new Microsoft.CodeAnalysis.Text.TextSpan(position, 1)) + "' expected to NOT be textual trigger character";
Assert.False(isTextualTriggerCharacterResult, assertText);
}
}
}
protected async Task VerifyCommonCommitCharactersAsync(string initialMarkup, string textTypedSoFar)
{
var commitCharacters = new[]
{
' ', '{', '}', '[', ']', '(', ')', '.', ',', ':',
';', '+', '-', '*', '/', '%', '&', '|', '^', '!',
'~', '=', '<', '>', '?', '@', '#', '\'', '\"', '\\'
};
await VerifyCommitCharactersAsync(initialMarkup, textTypedSoFar, commitCharacters);
}
protected async Task VerifyCommitCharactersAsync(string initialMarkup, string textTypedSoFar, char[] validChars, char[] invalidChars = null)
{
Assert.NotNull(validChars);
invalidChars = invalidChars ?? new[] { 'x' };
using (var workspace = await TestWorkspace.CreateCSharpAsync(initialMarkup))
{
var hostDocument = workspace.DocumentWithCursor;
var documentId = workspace.GetDocumentId(hostDocument);
var document = workspace.CurrentSolution.GetDocument(documentId);
var position = hostDocument.CursorPosition.Value;
var service = GetCompletionService(workspace);
var completionList = await GetCompletionListAsync(service, document, position, CompletionTrigger.Default);
var item = completionList.Items.First(i => i.DisplayText.StartsWith(textTypedSoFar));
foreach (var ch in validChars)
{
Assert.True(Controller.IsCommitCharacter(service.GetRules(), item, ch, textTypedSoFar), $"Expected '{ch}' to be a commit character");
}
foreach (var ch in invalidChars)
{
Assert.False(Controller.IsCommitCharacter(service.GetRules(), item, ch, textTypedSoFar), $"Expected '{ch}' NOT to be a commit character");
}
}
}
protected async Task TestCommonIsTextualTriggerCharacterAsync()
{
var alwaysTriggerList = new[]
......@@ -262,12 +155,5 @@ protected async Task TestCommonIsTextualTriggerCharacterAsync()
await VerifyTextualTriggerCharacterAsync(markup, shouldTriggerWithTriggerOnLettersEnabled: false, shouldTriggerWithTriggerOnLettersDisabled: false);
}
}
protected override ParseOptions CreateExperimentalParseOptions(ParseOptions parseOptions)
{
var options = (CSharpParseOptions)parseOptions;
var experimentalFeatures = new Dictionary<string, string>(); // no experimental features to enable
return options.WithFeatures(experimentalFeatures);
}
}
}
......@@ -39,8 +39,8 @@ public class TestAttribute : Attribute
public ConsoleColor Color { get; set; }
}";
await VerifySendEnterThroughToEnterAsync(markup, "Color =", sendThroughEnterEnabled: false, expected: false);
await VerifySendEnterThroughToEnterAsync(markup, "Color =", sendThroughEnterEnabled: true, expected: true);
await VerifySendEnterThroughToEditorAsync(markup, "Color =", sendThroughEnterEnabled: false, expected: false);
await VerifySendEnterThroughToEditorAsync(markup, "Color =", sendThroughEnterEnabled: true, expected: true);
}
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
......
......@@ -31,17 +31,17 @@ internal override CompletionProvider CreateCompletionProvider()
return new CrefCompletionProvider();
}
protected override async Task VerifyWorkerAsync(string code, int position, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger, bool checkForAbsence, bool experimental, int? glyph)
protected override async Task VerifyWorkerAsync(string code, int position, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger, bool checkForAbsence, int? glyph)
{
await VerifyAtPositionAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, experimental, glyph);
await VerifyAtEndOfFileAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, experimental, glyph);
await VerifyAtPositionAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph);
await VerifyAtEndOfFileAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph);
// Items cannot be partially written if we're checking for their absence,
// or if we're verifying that the list will show up (without specifying an actual item)
if (!checkForAbsence && expectedItemOrNull != null)
{
await VerifyAtPosition_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, experimental, glyph);
await VerifyAtEndOfFile_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, experimental, glyph);
await VerifyAtPosition_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph);
await VerifyAtEndOfFile_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph);
}
}
......
......@@ -36,8 +36,8 @@ public async Task IsTextualTriggerCharacterTest()
[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public async Task SendEnterThroughToEditorTest()
{
await VerifySendEnterThroughToEnterAsync("$$", "class", sendThroughEnterEnabled: false, expected: false);
await VerifySendEnterThroughToEnterAsync("$$", "class", sendThroughEnterEnabled: true, expected: true);
await VerifySendEnterThroughToEditorAsync("$$", "class", sendThroughEnterEnabled: false, expected: false);
await VerifySendEnterThroughToEditorAsync("$$", "class", sendThroughEnterEnabled: true, expected: true);
}
[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
......
......@@ -36,8 +36,8 @@ void Bar()
}
}";
await VerifySendEnterThroughToEnterAsync(markup, "a:", sendThroughEnterEnabled: false, expected: false);
await VerifySendEnterThroughToEnterAsync(markup, "a:", sendThroughEnterEnabled: true, expected: true);
await VerifySendEnterThroughToEditorAsync(markup, "a:", sendThroughEnterEnabled: false, expected: false);
await VerifySendEnterThroughToEditorAsync(markup, "a:", sendThroughEnterEnabled: true, expected: true);
}
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
......
......@@ -143,8 +143,8 @@ static void Main(string[] args)
}
}";
await VerifySendEnterThroughToEnterAsync(markup, "D", sendThroughEnterEnabled: false, expected: false);
await VerifySendEnterThroughToEnterAsync(markup, "D", sendThroughEnterEnabled: true, expected: true);
await VerifySendEnterThroughToEditorAsync(markup, "D", sendThroughEnterEnabled: false, expected: false);
await VerifySendEnterThroughToEditorAsync(markup, "D", sendThroughEnterEnabled: true, expected: true);
}
[WorkItem(828196, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/828196")]
......
......@@ -125,11 +125,11 @@ class C
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task CommitWithEnterObeysOption()
{
await VerifySendEnterThroughToEnterAsync("$$", "SnippetShortcu", sendThroughEnterEnabled: true, expected: false);
await VerifySendEnterThroughToEnterAsync("$$", "SnippetShortcut", sendThroughEnterEnabled: true, expected: true);
await VerifySendEnterThroughToEditorAsync("$$", "SnippetShortcu", sendThroughEnterEnabled: true, expected: false);
await VerifySendEnterThroughToEditorAsync("$$", "SnippetShortcut", sendThroughEnterEnabled: true, expected: true);
await VerifySendEnterThroughToEnterAsync("$$", "SnippetShortcu", sendThroughEnterEnabled: false, expected: false);
await VerifySendEnterThroughToEnterAsync("$$", "SnippetShortcut", sendThroughEnterEnabled: false, expected: false);
await VerifySendEnterThroughToEditorAsync("$$", "SnippetShortcu", sendThroughEnterEnabled: false, expected: false);
await VerifySendEnterThroughToEditorAsync("$$", "SnippetShortcut", sendThroughEnterEnabled: false, expected: false);
}
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
......
......@@ -47,8 +47,8 @@ class C
$$
}";
await VerifySendEnterThroughToEnterAsync(markup, "T", sendThroughEnterEnabled: false, expected: false);
await VerifySendEnterThroughToEnterAsync(markup, "T", sendThroughEnterEnabled: true, expected: true);
await VerifySendEnterThroughToEditorAsync(markup, "T", sendThroughEnterEnabled: false, expected: false);
await VerifySendEnterThroughToEditorAsync(markup, "T", sendThroughEnterEnabled: true, expected: true);
}
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
......
......@@ -7143,8 +7143,8 @@ public void foo()
var q = a?.$$AB.BA.AB.BA;
}
}";
await VerifyItemExistsAsync(markup, "AA", experimental: true);
await VerifyItemExistsAsync(markup, "AB", experimental: true);
await VerifyItemExistsAsync(markup, "AA");
await VerifyItemExistsAsync(markup, "AB");
}
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
......@@ -7166,8 +7166,8 @@ public void foo()
var q = a?.s?.$$;
}
}";
await VerifyItemExistsAsync(markup, "i", experimental: true);
await VerifyItemIsAbsentAsync(markup, "value", experimental: true);
await VerifyItemExistsAsync(markup, "i");
await VerifyItemIsAbsentAsync(markup, "value");
}
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
......@@ -7188,8 +7188,8 @@ public void foo()
var q = s?.$$i?.ToString();
}
}";
await VerifyItemExistsAsync(markup, "i", experimental: true);
await VerifyItemIsAbsentAsync(markup, "value", experimental: true);
await VerifyItemExistsAsync(markup, "i");
await VerifyItemIsAbsentAsync(markup, "value");
}
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
......@@ -7211,7 +7211,7 @@ public void foo()
var q = a?.s?[$$;
}
}";
await VerifyItemExistsAsync(markup, "System", experimental: true);
await VerifyItemExistsAsync(markup, "System");
}
[WorkItem(1109319, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1109319")]
......@@ -7550,7 +7550,7 @@ void foo()
}
}
";
await VerifyItemExistsAsync(markup, "WriteLine", experimental: true);
await VerifyItemExistsAsync(markup, "WriteLine");
}
[WorkItem(1024380, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1024380")]
......
......@@ -21,9 +21,9 @@ internal override CompletionProvider CreateCompletionProvider()
return new SymbolCompletionProvider();
}
protected override Task VerifyWorkerAsync(string code, int position, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger, bool checkForAbsence, bool experimental, int? glyph)
protected override Task VerifyWorkerAsync(string code, int position, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger, bool checkForAbsence, int? glyph)
{
return base.VerifyWorkerAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, SourceCodeKind.Regular, usePreviousCharAsTrigger, checkForAbsence, experimental, glyph);
return base.VerifyWorkerAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, SourceCodeKind.Regular, usePreviousCharAsTrigger, checkForAbsence, glyph);
}
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
......@@ -44,8 +44,8 @@ public async Task IsTextualTriggerCharacterTest()
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task SendEnterThroughToEditorTest()
{
await VerifySendEnterThroughToEnterAsync("class C { void M() { System.Console.$$", "Beep", sendThroughEnterEnabled: false, expected: false);
await VerifySendEnterThroughToEnterAsync("class C { void M() { System.Console.$$", "Beep", sendThroughEnterEnabled: true, expected: true);
await VerifySendEnterThroughToEditorAsync("class C { void M() { System.Console.$$", "Beep", sendThroughEnterEnabled: false, expected: false);
await VerifySendEnterThroughToEditorAsync("class C { void M() { System.Console.$$", "Beep", sendThroughEnterEnabled: true, expected: true);
}
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
......
......@@ -36,18 +36,18 @@ private async Task VerifyItemsAbsentAsync(string markup, params string[] items)
}
}
protected override async Task VerifyWorkerAsync(string code, int position, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger, bool checkForAbsence, bool experimental, int? glyph)
protected override async Task VerifyWorkerAsync(string code, int position, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger, bool checkForAbsence, int? glyph)
{
// We don't need to try writing comments in from of items in doc comments.
await VerifyAtPositionAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, experimental, glyph);
await VerifyAtEndOfFileAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, experimental, glyph);
await VerifyAtPositionAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph);
await VerifyAtEndOfFileAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph);
// Items cannot be partially written if we're checking for their absence,
// or if we're verifying that the list will show up (without specifying an actual item)
if (!checkForAbsence && expectedItemOrNull != null)
{
await VerifyAtPosition_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, experimental, glyph);
await VerifyAtEndOfFile_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, experimental, glyph);
await VerifyAtPosition_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph);
await VerifyAtEndOfFile_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph);
}
}
......
......@@ -29,7 +29,7 @@ protected override bool CompareItems(string actualItem, string expectedItem)
return actualItem.Equals(expectedItem, StringComparison.OrdinalIgnoreCase);
}
protected override Task VerifyWorkerAsync(string code, int position, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger, bool checkForAbsence, bool experimental, int? glyph)
protected override Task VerifyWorkerAsync(string code, int position, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger, bool checkForAbsence, int? glyph)
{
return BaseVerifyWorkerAsync(code,
position,
......
......@@ -29,7 +29,7 @@ protected override bool CompareItems(string actualItem, string expectedItem)
return actualItem.Equals(expectedItem, StringComparison.OrdinalIgnoreCase);
}
protected override Task VerifyWorkerAsync(string code, int position, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger, bool checkForAbsence, bool experimental, int? glyph)
protected override Task VerifyWorkerAsync(string code, int position, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger, bool checkForAbsence, int? glyph)
{
return BaseVerifyWorkerAsync(code,
position,
......@@ -87,8 +87,8 @@ public async Task IsTextualTriggerCharacterTest()
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task SendEnterThroughToEditorTest()
{
await VerifySendEnterThroughToEnterAsync("#r \"System$$", "System", sendThroughEnterEnabled: false, expected: false);
await VerifySendEnterThroughToEnterAsync("#r \"System$$", "System", sendThroughEnterEnabled: true, expected: false);
await VerifySendEnterThroughToEditorAsync("#r \"System$$", "System", sendThroughEnterEnabled: false, expected: false);
await VerifySendEnterThroughToEditorAsync("#r \"System$$", "System", sendThroughEnterEnabled: true, expected: false);
}
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
......
......@@ -58,6 +58,12 @@ internal CompletionServiceWithProviders GetCompletionService(Workspace workspace
internal abstract CompletionServiceWithProviders CreateCompletionService(
Workspace workspace, ImmutableArray<CompletionProvider> exclusiveProviders);
protected abstract string ItemPartiallyWritten(string expectedItemOrNull);
protected abstract Task<TestWorkspace> CreateWorkspaceAsync(string fileContents);
protected abstract Task BaseVerifyWorkerAsync(string code, int position, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger, bool checkForAbsence, int? glyph);
internal static CompletionHelper GetCompletionHelper(Document document, CompletionService service)
{
return CompletionHelper.GetHelper(document, service);
......@@ -136,13 +142,13 @@ internal static CompletionHelper GetCompletionHelper(Document document, Completi
}
}
private Task VerifyAsync(string markup, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger, bool checkForAbsence, bool experimental, int? glyph)
private Task VerifyAsync(string markup, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger, bool checkForAbsence, int? glyph)
{
string code;
int position;
MarkupTestFile.GetPosition(markup.NormalizeLineEndings(), out code, out position);
return VerifyWorkerAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, experimental, glyph);
return VerifyWorkerAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, glyph);
}
protected async Task VerifyCustomCommitProviderAsync(string markupBeforeCommit, string itemToCommit, string expectedCodeAfterCommit, SourceCodeKind? sourceCodeKind = null, char? commitChar = null)
......@@ -186,55 +192,55 @@ protected virtual bool CompareItems(string actualItem, string expectedItem)
return actualItem.Equals(expectedItem);
}
protected async Task VerifyItemExistsAsync(string markup, string expectedItem, string expectedDescriptionOrNull = null, SourceCodeKind? sourceCodeKind = null, bool usePreviousCharAsTrigger = false, bool experimental = false, int? glyph = null)
protected async Task VerifyItemExistsAsync(string markup, string expectedItem, string expectedDescriptionOrNull = null, SourceCodeKind? sourceCodeKind = null, bool usePreviousCharAsTrigger = false, int? glyph = null)
{
if (sourceCodeKind.HasValue)
{
await VerifyAsync(markup, expectedItem, expectedDescriptionOrNull, sourceCodeKind.Value, usePreviousCharAsTrigger, checkForAbsence: false, experimental: experimental, glyph: glyph);
await VerifyAsync(markup, expectedItem, expectedDescriptionOrNull, sourceCodeKind.Value, usePreviousCharAsTrigger, checkForAbsence: false, glyph: glyph);
}
else
{
await VerifyAsync(markup, expectedItem, expectedDescriptionOrNull, SourceCodeKind.Regular, usePreviousCharAsTrigger, checkForAbsence: false, experimental: experimental, glyph: glyph);
await VerifyAsync(markup, expectedItem, expectedDescriptionOrNull, SourceCodeKind.Script, usePreviousCharAsTrigger, checkForAbsence: false, experimental: experimental, glyph: glyph);
await VerifyAsync(markup, expectedItem, expectedDescriptionOrNull, SourceCodeKind.Regular, usePreviousCharAsTrigger, checkForAbsence: false, glyph: glyph);
await VerifyAsync(markup, expectedItem, expectedDescriptionOrNull, SourceCodeKind.Script, usePreviousCharAsTrigger, checkForAbsence: false, glyph: glyph);
}
}
protected async Task VerifyItemIsAbsentAsync(string markup, string expectedItem, string expectedDescriptionOrNull = null, SourceCodeKind? sourceCodeKind = null, bool usePreviousCharAsTrigger = false, bool experimental = false)
protected async Task VerifyItemIsAbsentAsync(string markup, string expectedItem, string expectedDescriptionOrNull = null, SourceCodeKind? sourceCodeKind = null, bool usePreviousCharAsTrigger = false)
{
if (sourceCodeKind.HasValue)
{
await VerifyAsync(markup, expectedItem, expectedDescriptionOrNull, sourceCodeKind.Value, usePreviousCharAsTrigger, checkForAbsence: true, experimental: experimental, glyph: null);
await VerifyAsync(markup, expectedItem, expectedDescriptionOrNull, sourceCodeKind.Value, usePreviousCharAsTrigger, checkForAbsence: true, glyph: null);
}
else
{
await VerifyAsync(markup, expectedItem, expectedDescriptionOrNull, SourceCodeKind.Regular, usePreviousCharAsTrigger, checkForAbsence: true, experimental: experimental, glyph: null);
await VerifyAsync(markup, expectedItem, expectedDescriptionOrNull, SourceCodeKind.Script, usePreviousCharAsTrigger, checkForAbsence: true, experimental: experimental, glyph: null);
await VerifyAsync(markup, expectedItem, expectedDescriptionOrNull, SourceCodeKind.Regular, usePreviousCharAsTrigger, checkForAbsence: true, glyph: null);
await VerifyAsync(markup, expectedItem, expectedDescriptionOrNull, SourceCodeKind.Script, usePreviousCharAsTrigger, checkForAbsence: true, glyph: null);
}
}
protected async Task VerifyAnyItemExistsAsync(string markup, SourceCodeKind? sourceCodeKind = null, bool usePreviousCharAsTrigger = false, bool experimental = false)
protected async Task VerifyAnyItemExistsAsync(string markup, SourceCodeKind? sourceCodeKind = null, bool usePreviousCharAsTrigger = false)
{
if (sourceCodeKind.HasValue)
{
await VerifyAsync(markup, expectedItemOrNull: null, expectedDescriptionOrNull: null, sourceCodeKind: sourceCodeKind.Value, usePreviousCharAsTrigger: usePreviousCharAsTrigger, checkForAbsence: false, experimental: experimental, glyph: null);
await VerifyAsync(markup, expectedItemOrNull: null, expectedDescriptionOrNull: null, sourceCodeKind: sourceCodeKind.Value, usePreviousCharAsTrigger: usePreviousCharAsTrigger, checkForAbsence: false, glyph: null);
}
else
{
await VerifyAsync(markup, expectedItemOrNull: null, expectedDescriptionOrNull: null, sourceCodeKind: SourceCodeKind.Regular, usePreviousCharAsTrigger: usePreviousCharAsTrigger, checkForAbsence: false, experimental: experimental, glyph: null);
await VerifyAsync(markup, expectedItemOrNull: null, expectedDescriptionOrNull: null, sourceCodeKind: SourceCodeKind.Script, usePreviousCharAsTrigger: usePreviousCharAsTrigger, checkForAbsence: false, experimental: experimental, glyph: null);
await VerifyAsync(markup, expectedItemOrNull: null, expectedDescriptionOrNull: null, sourceCodeKind: SourceCodeKind.Regular, usePreviousCharAsTrigger: usePreviousCharAsTrigger, checkForAbsence: false, glyph: null);
await VerifyAsync(markup, expectedItemOrNull: null, expectedDescriptionOrNull: null, sourceCodeKind: SourceCodeKind.Script, usePreviousCharAsTrigger: usePreviousCharAsTrigger, checkForAbsence: false, glyph: null);
}
}
protected async Task VerifyNoItemsExistAsync(string markup, SourceCodeKind? sourceCodeKind = null, bool usePreviousCharAsTrigger = false, bool experimental = false)
protected async Task VerifyNoItemsExistAsync(string markup, SourceCodeKind? sourceCodeKind = null, bool usePreviousCharAsTrigger = false)
{
if (sourceCodeKind.HasValue)
{
await VerifyAsync(markup, expectedItemOrNull: null, expectedDescriptionOrNull: null, sourceCodeKind: sourceCodeKind.Value, usePreviousCharAsTrigger: usePreviousCharAsTrigger, checkForAbsence: true, experimental: experimental, glyph: null);
await VerifyAsync(markup, expectedItemOrNull: null, expectedDescriptionOrNull: null, sourceCodeKind: sourceCodeKind.Value, usePreviousCharAsTrigger: usePreviousCharAsTrigger, checkForAbsence: true, glyph: null);
}
else
{
await VerifyAsync(markup, expectedItemOrNull: null, expectedDescriptionOrNull: null, sourceCodeKind: SourceCodeKind.Regular, usePreviousCharAsTrigger: usePreviousCharAsTrigger, checkForAbsence: true, experimental: experimental, glyph: null);
await VerifyAsync(markup, expectedItemOrNull: null, expectedDescriptionOrNull: null, sourceCodeKind: SourceCodeKind.Script, usePreviousCharAsTrigger: usePreviousCharAsTrigger, checkForAbsence: true, experimental: experimental, glyph: null);
await VerifyAsync(markup, expectedItemOrNull: null, expectedDescriptionOrNull: null, sourceCodeKind: SourceCodeKind.Regular, usePreviousCharAsTrigger: usePreviousCharAsTrigger, checkForAbsence: true, glyph: null);
await VerifyAsync(markup, expectedItemOrNull: null, expectedDescriptionOrNull: null, sourceCodeKind: SourceCodeKind.Script, usePreviousCharAsTrigger: usePreviousCharAsTrigger, checkForAbsence: true, glyph: null);
}
}
......@@ -248,16 +254,12 @@ protected async Task VerifyNoItemsExistAsync(string markup, SourceCodeKind? sour
/// <param name="expectedDescriptionOrNull">If this is null, the Description for the item is ignored.</param>
/// <param name="usePreviousCharAsTrigger">Whether or not the previous character in markup should be used to trigger IntelliSense for this provider. If false, invokes it through the invoke IntelliSense command.</param>
/// <param name="checkForAbsence">If true, checks for absence of a specific item (or that no items are returned from this CompletionProvider)</param>
protected virtual async Task VerifyWorkerAsync(string code, int position, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger, bool checkForAbsence, bool experimental, int? glyph)
protected virtual async Task VerifyWorkerAsync(
string code, int position,
string expectedItemOrNull, string expectedDescriptionOrNull,
SourceCodeKind sourceCodeKind,
bool usePreviousCharAsTrigger, bool checkForAbsence, int? glyph)
{
if (experimental)
{
foreach (var project in (await WorkspaceFixture.GetWorkspaceAsync()).Projects)
{
(await WorkspaceFixture.GetWorkspaceAsync()).OnParseOptionsChanged(project.Id, CreateExperimentalParseOptions(project.ParseOptions));
}
}
Glyph? expectedGlyph = null;
if (glyph.HasValue)
{
......@@ -274,11 +276,6 @@ protected virtual async Task VerifyWorkerAsync(string code, int position, string
}
}
protected virtual ParseOptions CreateExperimentalParseOptions(ParseOptions parseOptions)
{
return parseOptions;
}
/// <summary>
/// Override this to change parameters or return without verifying anything, e.g. for script sources. Or to test in other code contexts.
/// </summary>
......@@ -648,5 +645,122 @@ protected async Task VerifyItemInLinkedFilesAsync(string xmlString, string expec
}
}
}
protected Task VerifyAtPositionAsync(string code, int position, string insertText, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, int? glyph)
{
code = code.Substring(0, position) + insertText + code.Substring(position);
position += insertText.Length;
return BaseVerifyWorkerAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, glyph: glyph);
}
protected Task VerifyAtPositionAsync(string code, int position, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, int? glyph)
{
return VerifyAtPositionAsync(code, position, string.Empty, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph);
}
protected async Task VerifyAtEndOfFileAsync(string code, int position, string insertText, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, int? glyph)
{
// only do this if the placeholder was at the end of the text.
if (code.Length != position)
{
return;
}
code = code.Substring(startIndex: 0, length: position) + insertText;
position += insertText.Length;
await BaseVerifyWorkerAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, glyph);
}
protected Task VerifyAtPosition_ItemPartiallyWrittenAsync(string code, int position, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, int? glyph)
{
return VerifyAtPositionAsync(code, position, ItemPartiallyWritten(expectedItemOrNull), usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph);
}
protected Task VerifyAtEndOfFileAsync(string code, int position, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, int? glyph)
{
return VerifyAtEndOfFileAsync(code, position, string.Empty, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph);
}
protected Task VerifyAtEndOfFile_ItemPartiallyWrittenAsync(string code, int position, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, int? glyph)
{
return VerifyAtEndOfFileAsync(code, position, ItemPartiallyWritten(expectedItemOrNull), usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph);
}
protected async Task VerifyTextualTriggerCharacterAsync(
string markup, bool shouldTriggerWithTriggerOnLettersEnabled, bool shouldTriggerWithTriggerOnLettersDisabled)
{
await VerifyTextualTriggerCharacterWorkerAsync(markup, expectedTriggerCharacter: shouldTriggerWithTriggerOnLettersEnabled, triggerOnLetter: true);
await VerifyTextualTriggerCharacterWorkerAsync(markup, expectedTriggerCharacter: shouldTriggerWithTriggerOnLettersDisabled, triggerOnLetter: false);
}
private async Task VerifyTextualTriggerCharacterWorkerAsync(
string markup, bool expectedTriggerCharacter, bool triggerOnLetter)
{
using (var workspace = await CreateWorkspaceAsync(markup))
{
var document = workspace.Documents.Single();
var position = document.CursorPosition.Value;
var text = document.TextBuffer.CurrentSnapshot.AsText();
var options = workspace.Options.WithChangedOption(
CompletionOptions.TriggerOnTypingLetters, document.Project.Language, triggerOnLetter);
var trigger = CompletionTrigger.CreateInsertionTrigger(text[position]);
var service = GetCompletionService(workspace);
var isTextualTriggerCharacterResult = service.ShouldTriggerCompletion(text, position + 1, trigger, options: options);
if (expectedTriggerCharacter)
{
var assertText = "'" + text.ToString(new TextSpan(position, 1)) + "' expected to be textual trigger character";
Assert.True(isTextualTriggerCharacterResult, assertText);
}
else
{
var assertText = "'" + text.ToString(new TextSpan(position, 1)) + "' expected to NOT be textual trigger character";
Assert.False(isTextualTriggerCharacterResult, assertText);
}
}
}
protected async Task VerifyCommonCommitCharactersAsync(string initialMarkup, string textTypedSoFar)
{
var commitCharacters = new[]
{
' ', '{', '}', '[', ']', '(', ')', '.', ',', ':',
';', '+', '-', '*', '/', '%', '&', '|', '^', '!',
'~', '=', '<', '>', '?', '@', '#', '\'', '\"', '\\'
};
await VerifyCommitCharactersAsync(initialMarkup, textTypedSoFar, commitCharacters);
}
protected async Task VerifyCommitCharactersAsync(string initialMarkup, string textTypedSoFar, char[] validChars, char[] invalidChars = null)
{
Assert.NotNull(validChars);
invalidChars = invalidChars ?? new[] { 'x' };
using (var workspace = await CreateWorkspaceAsync(initialMarkup))
{
var hostDocument = workspace.DocumentWithCursor;
var documentId = workspace.GetDocumentId(hostDocument);
var document = workspace.CurrentSolution.GetDocument(documentId);
var position = hostDocument.CursorPosition.Value;
var service = GetCompletionService(workspace);
var completionList = await GetCompletionListAsync(service, document, position, CompletionTrigger.Default);
var item = completionList.Items.First(i => i.DisplayText.StartsWith(textTypedSoFar));
foreach (var ch in validChars)
{
Assert.True(Controller.IsCommitCharacter(service.GetRules(), item, ch, textTypedSoFar), $"Expected '{ch}' to be a commit character");
}
foreach (var ch in invalidChars)
{
Assert.False(Controller.IsCommitCharacter(service.GetRules(), item, ch, textTypedSoFar), $"Expected '{ch}' NOT to be a commit character");
}
}
}
}
}
}
\ No newline at end of file
......@@ -17,32 +17,36 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Completion.Complet
MyBase.New(workspaceFixture)
End Sub
Protected Overrides Function CreateWorkspaceAsync(fileContents As String) As Task(Of TestWorkspace)
Return TestWorkspace.CreateVisualBasicAsync(fileContents)
End Function
Friend Overrides Function CreateCompletionService(workspace As Workspace, exclusiveProviders As ImmutableArray(Of CompletionProvider)) As CompletionServiceWithProviders
Return New VisualBasicCompletionService(workspace, exclusiveProviders)
End Function
Protected Overrides Async Function VerifyWorkerAsync(code As String, position As Integer, expectedItemOrNull As String, expectedDescriptionOrNull As String, sourceCodeKind As SourceCodeKind, usePreviousCharAsTrigger As Boolean, checkForAbsence As Boolean, experimental As Boolean, glyph As Integer?) As Threading.Tasks.Task
Protected Overrides Function BaseVerifyWorkerAsync(code As String, position As Integer, expectedItemOrNull As String, expectedDescriptionOrNull As String, sourceCodeKind As SourceCodeKind, usePreviousCharAsTrigger As Boolean, checkForAbsence As Boolean, glyph As Integer?) As Task
Return MyBase.VerifyWorkerAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, glyph:=glyph)
End Function
Protected Overrides Async Function VerifyWorkerAsync(code As String, position As Integer, expectedItemOrNull As String, expectedDescriptionOrNull As String, sourceCodeKind As SourceCodeKind, usePreviousCharAsTrigger As Boolean, checkForAbsence As Boolean, glyph As Integer?) As Threading.Tasks.Task
' Script/interactive support removed for now.
' TODO: Re-enable these when interactive is back in the product.
If sourceCodeKind <> Microsoft.CodeAnalysis.SourceCodeKind.Regular Then
Return
End If
Await VerifyAtPositionAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, glyph, experimental)
Await VerifyAtEndOfFileAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, glyph, experimental)
Await VerifyAtPositionAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph)
Await VerifyAtEndOfFileAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph)
' Items cannot be partially written if we're checking for their absence,
' or if we're verifying that the list will show up (without specifying an actual item)
If Not checkForAbsence AndAlso expectedItemOrNull <> Nothing Then
Await VerifyAtPosition_ItemPartiallyWrittenAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, glyph, experimental)
Await VerifyAtEndOfFile_ItemPartiallyWrittenAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, glyph, experimental)
Await VerifyAtPosition_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph)
Await VerifyAtEndOfFile_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph)
End If
End Function
Protected Overridable Async Function BaseVerifyWorkerAsync(code As String, position As Integer, expectedItemOrNull As String, expectedDescriptionOrNull As String, sourceCodeKind As SourceCodeKind, usePreviousCharAsTrigger As Boolean, checkForAbsence As Boolean, glyph As Integer?, experimental As Boolean) As Threading.Tasks.Task
Await MyBase.VerifyWorkerAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, experimental:=experimental, glyph:=glyph)
End Function
Protected Overrides Async Function VerifyCustomCommitProviderWorkerAsync(codeBeforeCommit As String, position As Integer, itemToCommit As String, expectedCodeAfterCommit As String, sourceCodeKind As SourceCodeKind, Optional commitChar As Char? = Nothing) As Threading.Tasks.Task
' Script/interactive support removed for now.
' TODO: Re-enable these when interactive is back in the product.
......@@ -53,42 +57,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Completion.Complet
Await MyBase.VerifyCustomCommitProviderWorkerAsync(codeBeforeCommit, position, itemToCommit, expectedCodeAfterCommit, sourceCodeKind, commitChar)
End Function
Private Function VerifyAtPositionAsync(code As String, position As Integer, insertText As String, expectedItemOrNull As String, expectedDescriptionOrNull As String, sourceCodeKind As SourceCodeKind, usePreviousCharAsTrigger As Boolean, checkForAbsence As Boolean, glyph As Integer?, experimental As Boolean) As Threading.Tasks.Task
code = code.Substring(0, position) & insertText & code.Substring(position)
position += insertText.Length
Return MyBase.VerifyWorkerAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, experimental:=experimental, glyph:=glyph)
End Function
Protected Function VerifyAtPositionAsync(code As String, position As Integer, expectedItemOrNull As String, expectedDescriptionOrNull As String, sourceCodeKind As SourceCodeKind, usePreviousCharAsTrigger As Boolean, checkForAbsence As Boolean, glyph As Integer?, experimental As Boolean) As Threading.Tasks.Task
Return VerifyAtPositionAsync(code, position, String.Empty, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, glyph:=glyph, experimental:=experimental)
End Function
Private Function VerifyAtPosition_ItemPartiallyWrittenAsync(code As String, position As Integer, expectedItemOrNull As String, expectedDescriptionOrNull As String, sourceCodeKind As SourceCodeKind, usePreviousCharAsTrigger As Boolean, checkForAbsence As Boolean, glyph As Integer?, experimental As Boolean) As Threading.Tasks.Task
Return VerifyAtPositionAsync(code, position, ItemPartiallyWritten(expectedItemOrNull), expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, glyph:=glyph, experimental:=experimental)
End Function
Private Async Function VerifyAtEndOfFileAsync(code As String, position As Integer, insertText As String, expectedItemOrNull As String, expectedDescriptionOrNull As String, sourceCodeKind As SourceCodeKind, usePreviousCharAsTrigger As Boolean, checkForAbsence As Boolean, glyph As Integer?, experimental As Boolean) As Threading.Tasks.Task
' only do this if the placeholder was at the end of the text.
If code.Length <> position Then
Return
End If
code = code.Substring(startIndex:=0, length:=position) & insertText
position += insertText.Length
Await MyBase.VerifyWorkerAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, experimental:=experimental, glyph:=glyph)
End Function
Protected Function VerifyAtEndOfFileAsync(code As String, position As Integer, expectedItemOrNull As String, expectedDescriptionOrNull As String, sourceCodeKind As SourceCodeKind, usePreviousCharAsTrigger As Boolean, checkForAbsence As Boolean, glyph As Integer?, experimental As Boolean) As Threading.Tasks.Task
Return VerifyAtEndOfFileAsync(code, position, String.Empty, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, glyph, experimental)
End Function
Private Function VerifyAtEndOfFile_ItemPartiallyWrittenAsync(code As String, position As Integer, expectedItemOrNull As String, expectedDescriptionOrNull As String, sourceCodeKind As SourceCodeKind, usePreviousCharAsTrigger As Boolean, checkForAbsence As Boolean, glyph As Integer?, experimental As Boolean) As Threading.Tasks.Task
Return VerifyAtEndOfFileAsync(code, position, ItemPartiallyWritten(expectedItemOrNull), expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, glyph, experimental)
End Function
Private Shared Function ItemPartiallyWritten(expectedItemOrNull As String) As String
Protected Overrides Function ItemPartiallyWritten(expectedItemOrNull As String) As String
If expectedItemOrNull(0) = "[" Then
Return expectedItemOrNull.Substring(1, 1)
End If
......@@ -111,7 +80,8 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Completion.Complet
Return importsStatement & vbCrLf & vbCrLf & text
End Function
Protected Async Function VerifySendEnterThroughToEditorAsync(initialMarkup As String, textTypedSoFar As String, expected As Boolean) As Threading.Tasks.Task
Protected Async Function VerifySendEnterThroughToEditorAsync(
initialMarkup As String, textTypedSoFar As String, expected As Boolean) As Threading.Tasks.Task
Using workspace = Await TestWorkspace.CreateVisualBasicAsync(initialMarkup)
Dim hostDocument = workspace.DocumentWithCursor
Dim documentId = workspace.GetDocumentId(hostDocument)
......@@ -126,34 +96,6 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Completion.Complet
End Using
End Function
Protected Async Function VerifyCommonCommitCharactersAsync(initialMarkup As String, textTypedSoFar As String) As Threading.Tasks.Task
Dim commitCharacters = {" "c, ";"c, "("c, ")"c, "["c, "]"c, "{"c, "}"c, "."c, ","c, ":"c, "+"c, "-"c, "*"c, "/"c, "\"c, "^"c, "<"c, ">"c, "'"c, "="c}
Await VerifyCommitCharactersAsync(initialMarkup, textTypedSoFar, commitCharacters)
End Function
Protected Async Function VerifyCommitCharactersAsync(initialMarkup As String, textTypedSoFar As String, ParamArray chars As Char()) As Threading.Tasks.Task
Using workspace = Await TestWorkspace.CreateVisualBasicAsync(initialMarkup)
Dim hostDocument = workspace.DocumentWithCursor
Dim documentId = workspace.GetDocumentId(hostDocument)
Dim document = workspace.CurrentSolution.GetDocument(documentId)
Dim position = hostDocument.CursorPosition.Value
Dim service = GetCompletionService(workspace)
Dim completionList = Await GetCompletionListAsync(service, document, position, CompletionTrigger.Default)
Dim item = completionList.Items.First()
Dim helper = CompletionHelper.GetHelper(document, service)
For Each ch In chars
Assert.True(Controller.IsCommitCharacter(service.GetRules(), item, ch, textTypedSoFar), $"Expected '{ch}' to be a commit character")
Next
Dim chr = "x"c
Assert.False(Controller.IsCommitCharacter(service.GetRules(), item, chr, textTypedSoFar), $"Expected '{chr}' NOT to be a commit character")
End Using
End Function
Protected Async Function TestCommonIsTextualTriggerCharacterAsync() As Threading.Tasks.Task
Dim alwaysTriggerList =
{
......@@ -188,41 +130,5 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Completion.Complet
Await VerifyTextualTriggerCharacterAsync(markup, shouldTriggerWithTriggerOnLettersEnabled:=False, shouldTriggerWithTriggerOnLettersDisabled:=False)
Next
End Function
Protected Async Function VerifyTextualTriggerCharacterAsync(markup As String, shouldTriggerWithTriggerOnLettersEnabled As Boolean, shouldTriggerWithTriggerOnLettersDisabled As Boolean) As Threading.Tasks.Task
Await VerifyTextualTriggerCharacterWorkerAsync(markup, expectedTriggerCharacter:=shouldTriggerWithTriggerOnLettersEnabled, triggerOnLetter:=True)
Await VerifyTextualTriggerCharacterWorkerAsync(markup, expectedTriggerCharacter:=shouldTriggerWithTriggerOnLettersDisabled, triggerOnLetter:=False)
End Function
Private Async Function VerifyTextualTriggerCharacterWorkerAsync(markup As String, expectedTriggerCharacter As Boolean, triggerOnLetter As Boolean) As Threading.Tasks.Task
Dim code As String = Nothing
Dim position As Integer
MarkupTestFile.GetPosition(markup, code, position)
Using workspace = Await TestWorkspace.CreateVisualBasicAsync(code)
Dim document = workspace.Documents.First()
Dim text = document.TextBuffer.CurrentSnapshot.AsText()
Dim options = workspace.Options.WithChangedOption(CompletionOptions.TriggerOnTypingLetters, LanguageNames.VisualBasic, triggerOnLetter)
Dim trigger = CompletionTrigger.CreateInsertionTrigger(text(position))
Dim completionService = GetCompletionService(workspace)
Dim isTextualTriggerCharacterResult = completionService.ShouldTriggerCompletion(
text, position + 1, trigger, options:=options)
If expectedTriggerCharacter Then
Dim assertText = "'" & text.ToString(New TextSpan(position, 1)) & "' expected to be textual trigger character"
Assert.True(isTextualTriggerCharacterResult, assertText)
Else
Dim assertText = "'" & text.ToString(New TextSpan(position, 1)) & "' expected to NOT be textual trigger character"
Assert.False(isTextualTriggerCharacterResult, assertText)
End If
End Using
End Function
Protected Overrides Function CreateExperimentalParseOptions(parseOptions As ParseOptions) As ParseOptions
' There are no experimental parse options at this time.
Return parseOptions
End Function
End Class
End Namespace
......@@ -18,24 +18,24 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Completion.Complet
End Function
<Fact(), Trait(Traits.Feature, Traits.Features.KeywordRecommending)>
Public Async Function IsCommitCharacterTest() As Threading.Tasks.Task
Await VerifyCommonCommitCharactersAsync("$$", textTypedSoFar:="")
Public Async Function IsCommitCharacterTest() As Task
Await VerifyCommonCommitCharactersAsync("$$", textTypedSoFar:="C")
End Function
<Fact(), Trait(Traits.Feature, Traits.Features.KeywordRecommending)>
Public Async Function IsTextualTriggerCharacterTest() As Threading.Tasks.Task
Public Async Function IsTextualTriggerCharacterTest() As Task
Await TestCommonIsTextualTriggerCharacterAsync()
Await VerifyTextualTriggerCharacterAsync("foo$$(", shouldTriggerWithTriggerOnLettersEnabled:=True, shouldTriggerWithTriggerOnLettersDisabled:=True)
End Function
<Fact(), Trait(Traits.Feature, Traits.Features.KeywordRecommending)>
Public Async Function SendEnterThroughToEditorTest() As Threading.Tasks.Task
Public Async Function SendEnterThroughToEditorTest() As Task
Await VerifySendEnterThroughToEditorAsync("$$", "Class", expected:=True)
End Function
<Fact(), Trait(Traits.Feature, Traits.Features.KeywordRecommending)>
Public Async Function InEmptyFile() As Threading.Tasks.Task
Public Async Function InEmptyFile() As Task
Dim markup = "$$"
Await VerifyAnyItemExistsAsync(markup)
......@@ -182,7 +182,7 @@ End Class
<WorkItem(4167, "https://github.com/dotnet/roslyn/issues/4167")>
<Fact(), Trait(Traits.Feature, Traits.Features.KeywordRecommending)>
Public Async Function ImplementsAfterSub() As Threading.Tasks.Task
Public Async Function ImplementsAfterSub() As Task
Dim code = "
Interface I
End Interface
......
......@@ -13,14 +13,14 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Completion.Complet
MyBase.New(workspaceFixture)
End Sub
Protected Overrides Async Function VerifyWorkerAsync(code As String, position As Integer, expectedItemOrNull As String, expectedDescriptionOrNull As String, sourceCodeKind As SourceCodeKind, usePreviousCharAsTrigger As Boolean, checkForAbsence As Boolean, experimental As Boolean, glyph As Integer?) As Threading.Tasks.Task
Protected Overrides Async Function VerifyWorkerAsync(code As String, position As Integer, expectedItemOrNull As String, expectedDescriptionOrNull As String, sourceCodeKind As SourceCodeKind, usePreviousCharAsTrigger As Boolean, checkForAbsence As Boolean, glyph As Integer?) As Threading.Tasks.Task
' Script/interactive support removed for now.
' TODO: Re-enable these when interactive is back in the product.
If sourceCodeKind <> SourceCodeKind.Regular Then
Return
End If
Await BaseVerifyWorkerAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, glyph, experimental)
Await BaseVerifyWorkerAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, glyph)
End Function
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
......
......@@ -569,7 +569,7 @@ End Class</a>.Value
Dim position As Integer
MarkupTestFile.GetPosition(markup.NormalizeLineEndings(), code, position)
Await BaseVerifyWorkerAsync(code, position, "[Class]()", "Sub CBase.Class()", SourceCodeKind.Regular, False, False, Nothing, experimental:=False)
Await BaseVerifyWorkerAsync(code, position, "[Class]()", "Sub CBase.Class()", SourceCodeKind.Regular, False, False, Nothing)
End Function
<WpfFact, Trait(Traits.Feature, Traits.Features.Completion)>
......@@ -588,7 +588,7 @@ End Class</a>.Value
Dim position As Integer
MarkupTestFile.GetPosition(markup.NormalizeLineEndings(), code, position)
Await BaseVerifyWorkerAsync(code, position, "[Class]", "Property CBase.Class As Integer", SourceCodeKind.Regular, False, False, Nothing, experimental:=False)
Await BaseVerifyWorkerAsync(code, position, "[Class]", "Property CBase.Class As Integer", SourceCodeKind.Regular, False, False, Nothing)
End Function
<WpfFact, Trait(Traits.Feature, Traits.Features.Completion)>
......
......@@ -1343,7 +1343,7 @@ Class C
' We don't trigger intellisense within numeric literals, so we
' explicitly test only the "nothing typed" case.
' This is also the Dev12 behavior for suggesting labels.
Await VerifyAtPositionAsync(text, position, "10", Nothing, SourceCodeKind.Regular, usePreviousCharAsTrigger:=True, checkForAbsence:=False, glyph:=Nothing, experimental:=False)
Await VerifyAtPositionAsync(text, position, usePreviousCharAsTrigger:=True, expectedItemOrNull:="10", expectedDescriptionOrNull:=Nothing, sourceCodeKind:=SourceCodeKind.Regular, checkForAbsence:=False, glyph:=Nothing)
End Function
<WorkItem(541235, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541235")>
......@@ -5799,7 +5799,7 @@ Class [Class]
End Sub
End Class]]></code>.Value
Await VerifyItemExistsAsync(text, "ToString", experimental:=True)
Await VerifyItemExistsAsync(text, "ToString")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
......@@ -5813,7 +5813,7 @@ Class [Class]
End Sub
End Class]]></code>.Value
Await VerifyItemExistsAsync(text, "ToString", experimental:=True)
Await VerifyItemExistsAsync(text, "ToString")
End Function
<WorkItem(1041269, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1041269")>
......
......@@ -18,9 +18,9 @@ Namespace Tests
Return New XmlDocCommentCompletionProvider()
End Function
Protected Overrides Async Function VerifyWorkerAsync(code As String, position As Integer, expectedItemOrNull As String, expectedDescriptionOrNull As String, sourceCodeKind As SourceCodeKind, usePreviousCharAsTrigger As Boolean, checkForAbsence As Boolean, experimental As Boolean, glyph As Integer?) As Task
Await VerifyAtPositionAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, glyph, experimental)
Await VerifyAtEndOfFileAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, glyph, experimental)
Protected Overrides Async Function VerifyWorkerAsync(code As String, position As Integer, expectedItemOrNull As String, expectedDescriptionOrNull As String, sourceCodeKind As SourceCodeKind, usePreviousCharAsTrigger As Boolean, checkForAbsence As Boolean, glyph As Integer?) As Task
Await VerifyAtPositionAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph)
Await VerifyAtEndOfFileAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph)
End Function
Private Async Function VerifyItemsExistAsync(markup As String, ParamArray items() As String) As Task
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册