提交 847ad710 编写于 作者: R Ravi Chande

Replace the "Preselect" bool with an integer.

Add a public "MatchPriority" class that defines 2 possible values.
上级 7a9eda0e
......@@ -26,64 +26,65 @@ protected AbstractCSharpCompletionProviderTests(CSharpTestWorkspaceFixture works
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 async Task VerifyWorkerAsync(string code, int position, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger, bool checkForAbsence, bool experimental, int? glyph, int? matchPriority)
{
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, experimental, glyph, matchPriority);
await VerifyInFrontOfCommentAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, experimental, glyph, matchPriority);
await VerifyAtEndOfFileAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, experimental, glyph, matchPriority);
// 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, experimental, glyph, matchPriority);
await VerifyInFrontOfComment_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, experimental, glyph, matchPriority);
await VerifyAtEndOfFile_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, experimental, glyph, matchPriority);
}
}
protected Task BaseVerifyWorkerAsync(string code, int position, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger, bool checkForAbsence, int? glyph)
protected Task BaseVerifyWorkerAsync(string code, int position, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger, bool checkForAbsence, int? glyph, int? matchPriority)
{
return base.VerifyWorkerAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, experimental: false, glyph: glyph);
return base.VerifyWorkerAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, experimental: false, glyph: glyph, matchPriority: matchPriority);
}
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, bool experimental, int? glyph, int? matchPriority)
{
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, experimental, glyph: glyph, matchPriority: matchPriority);
}
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, bool experimental, int? glyph, int? matchPriority)
{
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, experimental, glyph: glyph, matchPriority: matchPriority);
}
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, bool experimental, int? glyph, int? matchPriority)
{
return VerifyInFrontOfCommentAsync(code, position, ItemPartiallyWritten(expectedItemOrNull), usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, experimental, glyph: glyph);
return VerifyInFrontOfCommentAsync(code, position, ItemPartiallyWritten(expectedItemOrNull), usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, experimental, glyph: glyph, matchPriority: matchPriority);
}
protected Task VerifyAtPositionAsync(string code, int position, string insertText, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, bool experimental, int? glyph)
protected Task VerifyAtPositionAsync(string code, int position, string insertText, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, bool experimental, int? glyph, int? matchPriority)
{
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, experimental, glyph: glyph, matchPriority: matchPriority);
}
protected Task VerifyAtPositionAsync(string code, int position, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, bool experimental, int? glyph)
protected Task VerifyAtPositionAsync(string code, int position, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, bool experimental, int? glyph, int? matchPriority)
{
return VerifyAtPositionAsync(code, position, string.Empty, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, experimental, glyph);
return VerifyAtPositionAsync(code, position, string.Empty, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, experimental, glyph, matchPriority);
}
protected Task VerifyAtPosition_ItemPartiallyWrittenAsync(string code, int position, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, bool experimental, int? glyph)
protected Task VerifyAtPosition_ItemPartiallyWrittenAsync(string code, int position, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, bool experimental, int? glyph, int? matchPriority)
{
return VerifyAtPositionAsync(code, position, ItemPartiallyWritten(expectedItemOrNull), usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, experimental, glyph);
return VerifyAtPositionAsync(code, position, ItemPartiallyWritten(expectedItemOrNull), usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, experimental, glyph, matchPriority);
}
private async Task VerifyAtEndOfFileAsync(string code, int position, string insertText, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, bool experimental, int? 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, int? matchPriority)
{
// only do this if the placeholder was at the end of the text.
if (code.Length != position)
......@@ -94,17 +95,17 @@ private async Task VerifyAtEndOfFileAsync(string code, int position, string inse
code = code.Substring(startIndex: 0, length: position) + insertText;
position += insertText.Length;
await base.VerifyWorkerAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, experimental, glyph);
await base.VerifyWorkerAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, experimental, glyph, matchPriority);
}
protected Task VerifyAtEndOfFileAsync(string code, int position, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, bool experimental, int? glyph)
protected Task VerifyAtEndOfFileAsync(string code, int position, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, bool experimental, int? glyph, int? matchPriority)
{
return VerifyAtEndOfFileAsync(code, position, string.Empty, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, experimental, glyph);
return VerifyAtEndOfFileAsync(code, position, string.Empty, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, experimental, glyph, matchPriority);
}
protected Task VerifyAtEndOfFile_ItemPartiallyWrittenAsync(string code, int position, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, bool experimental, int? glyph)
protected Task VerifyAtEndOfFile_ItemPartiallyWrittenAsync(string code, int position, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, bool experimental, int? glyph, int? matchPriority)
{
return VerifyAtEndOfFileAsync(code, position, ItemPartiallyWritten(expectedItemOrNull), usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, experimental, glyph);
return VerifyAtEndOfFileAsync(code, position, ItemPartiallyWritten(expectedItemOrNull), usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, experimental, glyph, matchPriority);
}
private static string ItemPartiallyWritten(string expectedItemOrNull)
......
......@@ -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, bool experimental, int? glyph, int? matchPriority)
{
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, experimental, glyph, matchPriority);
await VerifyAtEndOfFileAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, experimental, glyph, matchPriority);
// 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, experimental, glyph, matchPriority);
await VerifyAtEndOfFile_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, experimental, glyph, matchPriority);
}
}
......
......@@ -465,5 +465,31 @@ enum Colors
";
await VerifyItemExistsAsync(markup, "Colors");
}
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task NotAfterDot()
{
var markup =
@"namespace ConsoleApplication253
{
class Program
{
static void Main(string[] args)
{
M(E.$$)
}
static void M(E e) { }
}
enum E
{
A,
B,
}
}
";
await VerifyNoItemsExistAsync(markup);
}
}
}
......@@ -700,8 +700,8 @@ public class SomeClass : Base
int position;
MarkupTestFile.GetPosition(markup, out code, out position);
await BaseVerifyWorkerAsync(code, position, "@class()", "void Base.@class()", SourceCodeKind.Regular, false, false, null);
await BaseVerifyWorkerAsync(code, position, "@class()", "void Base.@class()", SourceCodeKind.Script, false, false, null);
await BaseVerifyWorkerAsync(code, position, "@class()", "void Base.@class()", SourceCodeKind.Regular, false, false, null, null);
await BaseVerifyWorkerAsync(code, position, "@class()", "void Base.@class()", SourceCodeKind.Script, false, false, null, null);
}
[WpfFact, Trait(Traits.Feature, Traits.Features.Completion)]
......@@ -721,8 +721,8 @@ public class SomeClass : Base
int position;
MarkupTestFile.GetPosition(markup, out code, out position);
await BaseVerifyWorkerAsync(code, position, "@class", "int Base.@class { get; set; }", SourceCodeKind.Regular, false, false, null);
await BaseVerifyWorkerAsync(code, position, "@class", "int Base.@class { get; set; }", SourceCodeKind.Script, false, false, null);
await BaseVerifyWorkerAsync(code, position, "@class", "int Base.@class { get; set; }", SourceCodeKind.Regular, false, false, null, null);
await BaseVerifyWorkerAsync(code, position, "@class", "int Base.@class { get; set; }", SourceCodeKind.Script, false, false, null, null);
}
[WpfFact, Trait(Traits.Feature, Traits.Features.Completion)]
......
......@@ -2,6 +2,7 @@
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Completion;
using Microsoft.CodeAnalysis.Completion.Providers;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Completion.Providers;
using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.CompletionProviders;
......@@ -8473,4 +8474,4 @@ public async Task NoCompletionInShebangComments()
await VerifyNoItemsExistAsync("#! S$$", sourceCodeKind: SourceCodeKind.Script, usePreviousCharAsTrigger: true);
}
}
}
}
\ No newline at end of file
......@@ -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, bool experimental, int? glyph, int? matchPriority)
{
return base.VerifyWorkerAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, SourceCodeKind.Regular, usePreviousCharAsTrigger, checkForAbsence, experimental, glyph);
return base.VerifyWorkerAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, SourceCodeKind.Regular, usePreviousCharAsTrigger, checkForAbsence, experimental, glyph, matchPriority);
}
[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, bool experimental, int? glyph, int? matchPriority)
{
// 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, experimental, glyph, matchPriority);
await VerifyAtEndOfFileAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, experimental, glyph, matchPriority);
// 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, experimental, glyph, matchPriority);
await VerifyAtEndOfFile_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, experimental, glyph, matchPriority);
}
}
......
......@@ -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, bool experimental, int? glyph, int? matchPriority)
{
return BaseVerifyWorkerAsync(code,
position,
......@@ -38,7 +38,8 @@ protected override Task VerifyWorkerAsync(string code, int position, string expe
sourceCodeKind,
usePreviousCharAsTrigger,
checkForAbsence,
glyph);
glyph,
matchPriority);
}
private async Task VerifyItemExistsInScriptAsync(string markup, string expected)
......
......@@ -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, bool experimental, int? glyph, int? matchPriority)
{
return BaseVerifyWorkerAsync(code,
position,
......@@ -38,7 +38,8 @@ protected override Task VerifyWorkerAsync(string code, int position, string expe
sourceCodeKind,
usePreviousCharAsTrigger,
checkForAbsence,
glyph);
glyph,
matchPriority);
}
private async Task VerifyItemsExistInScriptAndInteractiveAsync(string code, params string[] expected)
......
......@@ -260,4 +260,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
......@@ -5,16 +5,12 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Completion;
using Microsoft.CodeAnalysis.Completion.Providers;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Extensions.ContextQuery;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Test.Utilities;
using Roslyn.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Recommendations
......@@ -24,18 +20,17 @@ public abstract class RecommenderTests : TestBase
protected string keywordText;
internal Func<int, CSharpSyntaxContext, Task<IEnumerable<RecommendedKeyword>>> RecommendKeywordsAsync;
public async Task VerifyWorkerAsync(string markup, bool absent, CSharpParseOptions options = null)
internal async Task VerifyWorkerAsync(string markup, bool absent, CSharpParseOptions options = null, int? matchPriority = null)
{
string code;
int position;
MarkupTestFile.GetPosition(markup, out code, out position);
await VerifyAtPositionAsync(code, position, absent, options: options);
await VerifyInFrontOfCommentAsync(code, position, absent, options: options);
await VerifyAtEndOfFileAsync(code, position, absent, options: options);
await VerifyAtPosition_KeywordPartiallyWrittenAsync(code, position, absent, options: options);
await VerifyInFrontOfComment_KeywordPartiallyWrittenAsync(code, position, absent, options: options);
await VerifyAtEndOfFile_KeywordPartiallyWrittenAsync(code, position, absent, options: options);
await VerifyAtPositionAsync(code, position, absent, options: options, matchPriority: matchPriority);
await VerifyInFrontOfCommentAsync(code, position, absent, options: options, matchPriority: matchPriority);
await VerifyAtEndOfFileAsync(code, position, absent, options: options, matchPriority: matchPriority);
await VerifyAtPosition_KeywordPartiallyWrittenAsync(code, position, absent, options: options, matchPriority: matchPriority);
await VerifyInFrontOfComment_KeywordPartiallyWrittenAsync(code, position, absent, options: options, matchPriority: matchPriority);
await VerifyAtEndOfFile_KeywordPartiallyWrittenAsync(code, position, absent, options: options, matchPriority: matchPriority);
}
private Task VerifyInFrontOfCommentAsync(
......@@ -43,16 +38,17 @@ public async Task VerifyWorkerAsync(string markup, bool absent, CSharpParseOptio
int position,
bool absent,
string insertText,
CSharpParseOptions options)
CSharpParseOptions options,
int? matchPriority)
{
text = text.Substring(0, position) + insertText + "/**/" + text.Substring(position);
position += insertText.Length;
return CheckResultAsync(text, position, absent, options);
return CheckResultAsync(text, position, absent, options, matchPriority);
}
private Task CheckResultAsync(string text, int position, bool absent, CSharpParseOptions options)
private Task CheckResultAsync(string text, int position, bool absent, CSharpParseOptions options, int? matchPriority)
{
var tree = SyntaxFactory.ParseSyntaxTree(text, options: options);
var compilation = CSharpCompilation.Create(
......@@ -67,10 +63,10 @@ private Task CheckResultAsync(string text, int position, bool absent, CSharpPars
var semanticModel = compilation.GetSemanticModel(tree);
var context = CSharpSyntaxContext.CreateContext_Test(semanticModel, position, CancellationToken.None);
return CheckResultAsync(absent, position, context, semanticModel);
return CheckResultAsync(absent, position, context, semanticModel, matchPriority);
}
private async Task CheckResultAsync(bool absent, int position, CSharpSyntaxContext context, SemanticModel semanticModel)
private async Task CheckResultAsync(bool absent, int position, CSharpSyntaxContext context, SemanticModel semanticModel, int? matchPriority)
{
if (absent)
{
......@@ -88,21 +84,21 @@ private async Task CheckResultAsync(bool absent, int position, CSharpSyntaxConte
}
else
{
var result = (await RecommendKeywordsAsync(position, context)).Select(k => k.Keyword);
var result = (await RecommendKeywordsAsync(position, context)).Single();
Assert.NotNull(result);
Assert.Equal(keywordText, result.Single());
Assert.Equal(keywordText, result.Keyword);
}
}
}
private Task VerifyInFrontOfCommentAsync(string text, int cursorPosition, bool absent, CSharpParseOptions options)
private Task VerifyInFrontOfCommentAsync(string text, int cursorPosition, bool absent, CSharpParseOptions options, int? matchPriority)
{
return VerifyInFrontOfCommentAsync(text, cursorPosition, absent, string.Empty, options: options);
return VerifyInFrontOfCommentAsync(text, cursorPosition, absent, string.Empty, options: options, matchPriority: matchPriority);
}
private Task VerifyInFrontOfComment_KeywordPartiallyWrittenAsync(string text, int position, bool absent, CSharpParseOptions options)
private Task VerifyInFrontOfComment_KeywordPartiallyWrittenAsync(string text, int position, bool absent, CSharpParseOptions options, int? matchPriority)
{
return VerifyInFrontOfCommentAsync(text, position, absent, keywordText.Substring(0, 1), options: options);
return VerifyInFrontOfCommentAsync(text, position, absent, keywordText.Substring(0, 1), options: options, matchPriority: matchPriority);
}
private Task VerifyAtPositionAsync(
......@@ -110,23 +106,24 @@ private Task VerifyInFrontOfComment_KeywordPartiallyWrittenAsync(string text, in
int position,
bool absent,
string insertText,
CSharpParseOptions options)
CSharpParseOptions options,
int? matchPriority)
{
text = text.Substring(0, position) + insertText + text.Substring(position);
position += insertText.Length;
return CheckResultAsync(text, position, absent, options);
return CheckResultAsync(text, position, absent, options, matchPriority);
}
private Task VerifyAtPositionAsync(string text, int position, bool absent, CSharpParseOptions options)
private Task VerifyAtPositionAsync(string text, int position, bool absent, CSharpParseOptions options, int? matchPriority)
{
return VerifyAtPositionAsync(text, position, absent, string.Empty, options: options);
return VerifyAtPositionAsync(text, position, absent, string.Empty, options: options, matchPriority: matchPriority);
}
private Task VerifyAtPosition_KeywordPartiallyWrittenAsync(string text, int position, bool absent, CSharpParseOptions options)
private Task VerifyAtPosition_KeywordPartiallyWrittenAsync(string text, int position, bool absent, CSharpParseOptions options, int? matchPriority)
{
return VerifyAtPositionAsync(text, position, absent, keywordText.Substring(0, 1), options: options);
return VerifyAtPositionAsync(text, position, absent, keywordText.Substring(0, 1), options: options, matchPriority: matchPriority);
}
private async Task VerifyAtEndOfFileAsync(
......@@ -134,7 +131,8 @@ private Task VerifyAtPosition_KeywordPartiallyWrittenAsync(string text, int posi
int position,
bool absent,
string insertText,
CSharpParseOptions options)
CSharpParseOptions options,
int? matchPriority)
{
// only do this if the placeholder was at the end of the text.
if (text.Length != position)
......@@ -146,20 +144,20 @@ private Task VerifyAtPosition_KeywordPartiallyWrittenAsync(string text, int posi
position += insertText.Length;
await CheckResultAsync(text, position, absent, options);
await CheckResultAsync(text, position, absent, options, matchPriority);
}
private Task VerifyAtEndOfFileAsync(string text, int position, bool absent, CSharpParseOptions options)
private Task VerifyAtEndOfFileAsync(string text, int position, bool absent, CSharpParseOptions options, int? matchPriority)
{
return VerifyAtEndOfFileAsync(text, position, absent, string.Empty, options: options);
return VerifyAtEndOfFileAsync(text, position, absent, string.Empty, options: options, matchPriority: matchPriority);
}
private Task VerifyAtEndOfFile_KeywordPartiallyWrittenAsync(string text, int position, bool absent, CSharpParseOptions options)
private Task VerifyAtEndOfFile_KeywordPartiallyWrittenAsync(string text, int position, bool absent, CSharpParseOptions options, int? matchPriority)
{
return VerifyAtEndOfFileAsync(text, position, absent, keywordText.Substring(0, 1), options: options);
return VerifyAtEndOfFileAsync(text, position, absent, keywordText.Substring(0, 1), options: options, matchPriority: matchPriority);
}
protected async Task VerifyKeywordAsync(string text, CSharpParseOptions options = null, CSharpParseOptions scriptOptions = null)
internal async Task VerifyKeywordAsync(string text, CSharpParseOptions options = null, CSharpParseOptions scriptOptions = null, int? matchPriority = null)
{
// run the verification in both context(normal and script)
await VerifyWorkerAsync(text, absent: false, options: options);
......
......@@ -77,7 +77,7 @@ public virtual bool MatchesFilterText(CompletionItem item, string filterText, Co
// MRU list, then we definitely want to include it.
if (filterText.Length == 0)
{
if (item.Rules.Preselect || (!recentItems.IsDefault && GetRecentItemIndex(recentItems, item) < 0))
if (item.Rules.MatchPriority > MatchPriority.Default || (!recentItems.IsDefault && GetRecentItemIndex(recentItems, item) < 0))
{
return true;
}
......@@ -191,12 +191,17 @@ private PatternMatcher GetFallbackPatternMatcher(string value)
/// </summary>
public virtual bool IsBetterFilterMatch(CompletionItem item1, CompletionItem item2, string filterText, CompletionTrigger trigger, CompletionFilterReason filterReason, ImmutableArray<string> recentItems = default(ImmutableArray<string>))
{
var match1 = GetMatch(item1, GetCultureSpecificQuirks(filterText));
var match2 = GetMatch(item2, GetCultureSpecificQuirks(filterText));
return IsBetterFilterMatchWorker(item1, item2, filterText, recentItems, comparePriorityBeforeCapitalization: false);
}
protected bool IsBetterFilterMatchWorker(CompletionItem item1, CompletionItem item2, string filterText, ImmutableArray<string> recentItems, bool comparePriorityBeforeCapitalization)
{
var match1 = GetMatch(item1, filterText);
var match2 = GetMatch(item2, filterText);
if (match1 != null && match2 != null)
{
var result = CompareMatches(match1.Value, match2.Value, item1, item2);
var result = CompareMatches(match1.Value, match2.Value, item1, item2, comparePriorityBeforeCapitalization);
if (result != 0)
{
return result < 0;
......@@ -213,9 +218,9 @@ public virtual bool IsBetterFilterMatch(CompletionItem item1, CompletionItem ite
// If they both seemed just as good, but they differ on preselection, then
// item1 is better if it is preselected, otherwise it is worse.
if (item1.Rules.Preselect != item2.Rules.Preselect)
if (item1.Rules.MatchPriority != item2.Rules.MatchPriority)
{
return item1.Rules.Preselect;
return item1.Rules.MatchPriority > item2.Rules.MatchPriority;
}
// Prefer things with a keyword tag, if the filter texts are the same.
......@@ -270,7 +275,7 @@ protected int GetPrefixLength(string text, string pattern)
return x;
}
protected int CompareMatches(PatternMatch match1, PatternMatch match2, CompletionItem item1, CompletionItem item2)
protected int CompareMatches(PatternMatch match1, PatternMatch match2, CompletionItem item1, CompletionItem item2, bool comparePriorityBeforeCapitalization)
{
int diff;
......@@ -297,11 +302,11 @@ protected int CompareMatches(PatternMatch match1, PatternMatch match2, Completio
}
// preselected items are prefered
if (item1.Rules.Preselect && !item2.Rules.Preselect)
if (comparePriorityBeforeCapitalization && item1.Rules.MatchPriority > item2.Rules.MatchPriority)
{
return -1;
}
else if (item2.Rules.Preselect && !item1.Rules.Preselect)
else if (comparePriorityBeforeCapitalization && item2.Rules.MatchPriority > item1.Rules.MatchPriority)
{
return 1;
}
......@@ -438,7 +443,7 @@ public virtual bool SendEnterThroughToEditor(CompletionItem item, string textTyp
/// </summary>
public virtual bool ShouldSoftSelectItem(CompletionItem item, string filterText, CompletionTrigger trigger)
{
return filterText.Length == 0 && !item.Rules.Preselect;
return filterText.Length == 0 && item.Rules.MatchPriority == MatchPriority.Default;
}
protected bool IsObjectCreationItem(CompletionItem item)
......
......@@ -33,7 +33,7 @@ public DescriptionModifyingCompletionItem(CompletionItem completionItem, IComple
glyph: completionItem.Glyph,
sortText: completionItem.SortText,
filterText: completionItem.FilterText,
preselect: completionItem.Preselect,
matchPriority: completionItem.MatchPriority,
isBuilder: completionItem.IsBuilder,
showsWarningIcon: completionItem.ShowsWarningIcon,
shouldFormatOnCommit: completionItem.ShouldFormatOnCommit,
......
......@@ -87,8 +87,7 @@ internal static CompletionHelper GetCompletionHelper(Document document, Completi
return service.GetCompletionsAsync(document, position, triggerInfo, options: options);
}
private async Task CheckResultsAsync(
Document document, int position, string expectedItemOrNull, string expectedDescriptionOrNull, bool usePreviousCharAsTrigger, bool checkForAbsence, Glyph? glyph)
private async Task CheckResultsAsync(Document document, int position, string expectedItemOrNull, string expectedDescriptionOrNull, bool usePreviousCharAsTrigger, bool checkForAbsence, Glyph? glyph, int? matchPriority)
{
var code = (await document.GetTextAsync()).ToString();
......@@ -132,18 +131,19 @@ internal static CompletionHelper GetCompletionHelper(Document document, Completi
{
AssertEx.Any(items, c => CompareItems(c.DisplayText, expectedItemOrNull)
&& (expectedDescriptionOrNull != null ? completionService.GetDescriptionAsync(document, c).Result.Text == expectedDescriptionOrNull : true)
&& (glyph.HasValue ? CompletionHelper.TagsEqual(c.Tags, GlyphTags.GetTags(glyph.Value)) : true));
&& (glyph.HasValue ? CompletionHelper.TagsEqual(c.Tags, GlyphTags.GetTags(glyph.Value)) : true)
&& (matchPriority.HasValue ? (int)c.Rules.MatchPriority == matchPriority.Value : true ));
}
}
}
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, bool experimental, int? glyph, int? matchPriority)
{
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, experimental, glyph, matchPriority);
}
protected async Task VerifyCustomCommitProviderAsync(string markupBeforeCommit, string itemToCommit, string expectedCodeAfterCommit, SourceCodeKind? sourceCodeKind = null, char? commitChar = null)
......@@ -187,16 +187,16 @@ 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, bool experimental = false, int? glyph = null, int? matchPriority = 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, experimental: experimental, glyph: glyph, matchPriority: matchPriority);
}
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, experimental: experimental, glyph: glyph, matchPriority: matchPriority);
await VerifyAsync(markup, expectedItem, expectedDescriptionOrNull, SourceCodeKind.Script, usePreviousCharAsTrigger, checkForAbsence: false, experimental: experimental, glyph: glyph, matchPriority: matchPriority);
}
}
......@@ -204,12 +204,12 @@ protected async Task VerifyItemIsAbsentAsync(string markup, string expectedItem,
{
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, experimental: experimental, glyph: null, matchPriority: 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, experimental: experimental, glyph: null, matchPriority: null);
await VerifyAsync(markup, expectedItem, expectedDescriptionOrNull, SourceCodeKind.Script, usePreviousCharAsTrigger, checkForAbsence: true, experimental: experimental, glyph: null, matchPriority: null);
}
}
......@@ -217,12 +217,12 @@ protected async Task VerifyAnyItemExistsAsync(string markup, SourceCodeKind? sou
{
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, experimental: experimental, glyph: null, matchPriority: 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, experimental: experimental, glyph: null, matchPriority: null);
await VerifyAsync(markup, expectedItemOrNull: null, expectedDescriptionOrNull: null, sourceCodeKind: SourceCodeKind.Script, usePreviousCharAsTrigger: usePreviousCharAsTrigger, checkForAbsence: false, experimental: experimental, glyph: null, matchPriority: null);
}
}
......@@ -230,12 +230,12 @@ protected async Task VerifyNoItemsExistAsync(string markup, SourceCodeKind? sour
{
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, experimental: experimental, glyph: null, matchPriority: 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, experimental: experimental, glyph: null, matchPriority: null);
await VerifyAsync(markup, expectedItemOrNull: null, expectedDescriptionOrNull: null, sourceCodeKind: SourceCodeKind.Script, usePreviousCharAsTrigger: usePreviousCharAsTrigger, checkForAbsence: true, experimental: experimental, glyph: null, matchPriority: null);
}
}
......@@ -249,7 +249,7 @@ 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, bool experimental, int? glyph, int? matchPriority)
{
if (experimental)
{
......@@ -266,12 +266,12 @@ protected virtual async Task VerifyWorkerAsync(string code, int position, string
}
var document1 = await WorkspaceFixture.UpdateDocumentAsync(code, sourceCodeKind);
await CheckResultsAsync(document1, position, expectedItemOrNull, expectedDescriptionOrNull, usePreviousCharAsTrigger, checkForAbsence, expectedGlyph);
await CheckResultsAsync(document1, position, expectedItemOrNull, expectedDescriptionOrNull, usePreviousCharAsTrigger, checkForAbsence, expectedGlyph, matchPriority);
if (await CanUseSpeculativeSemanticModelAsync(document1, position))
{
var document2 = await WorkspaceFixture.UpdateDocumentAsync(code, sourceCodeKind, cleanBeforeUpdate: false);
await CheckResultsAsync(document2, position, expectedItemOrNull, expectedDescriptionOrNull, usePreviousCharAsTrigger, checkForAbsence, expectedGlyph);
await CheckResultsAsync(document2, position, expectedItemOrNull, expectedDescriptionOrNull, usePreviousCharAsTrigger, checkForAbsence, expectedGlyph, matchPriority);
}
}
......@@ -558,8 +558,7 @@ private Task VerifyItemInSameProjectAsync(string markup, string referencedCode,
{
AssertEx.Any(completionList.Items, c => CompareItems(c.DisplayText, expectedItem));
// Throw if multiple to indicate a bad test case
var item = completionList.Items.Single(c => CompareItems(c.DisplayText, expectedItem));
var item = completionList.Items.First(c => CompareItems(c.DisplayText, expectedItem));
var description = await completionService.GetDescriptionAsync(document, item);
if (expectedSymbols == 1)
......
......@@ -66,7 +66,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.Completion
If filterReason = CompletionFilterReason.BackspaceOrDelete Then
Dim prefixLength1 = GetPrefixLength(item1.FilterText, filterText)
Dim prefixLength2 = GetPrefixLength(item2.FilterText, filterText)
Return prefixLength1 > prefixLength2 OrElse ((item1.Rules.Preselect AndAlso Not item2.Rules.Preselect) AndAlso Not IsEnumMemberItem(item1))
Return prefixLength1 > prefixLength2 OrElse ((item1.Rules.MatchPriority > MatchPriority.Default AndAlso Not item2.Rules.MatchPriority > MatchPriority.Default) AndAlso Not IsEnumMemberItem(item1))
End If
If IsEnumMemberItem(item2) Then
......@@ -87,7 +87,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.Completion
End If
End If
Return MyBase.IsBetterFilterMatch(item1, item2, filterText, trigger, filterReason, recentItems)
Return IsBetterFilterMatchWorker(item1, item2, filterText, recentItems, comparePriorityBeforeCapitalization:=True)
End Function
Public Overrides Function ShouldSoftSelectItem(item As CompletionItem, filterText As String, trigger As CompletionTrigger) As Boolean
......
......@@ -20,26 +20,26 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Completion.Complet
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 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?, matchPriority 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, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, glyph, matchPriority, experimental)
Await VerifyAtEndOfFileAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, glyph, matchPriority, experimental)
' 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, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, glyph, matchPriority, experimental)
Await VerifyAtEndOfFile_ItemPartiallyWrittenAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, glyph, matchPriority, experimental)
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)
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, matchPriority As Integer?) As Threading.Tasks.Task
Await MyBase.VerifyWorkerAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, experimental:=experimental, glyph:=glyph, matchPriority:=matchPriority)
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
......@@ -52,22 +52,23 @@ 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
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?, matchPriority 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)
Return MyBase.VerifyWorkerAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, experimental:=experimental, glyph:=glyph, matchPriority:=matchPriority)
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)
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?, matchPriority As Integer?, experimental As Boolean) As Threading.Tasks.Task
Return VerifyAtPositionAsync(code, position, String.Empty, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, glyph:=glyph, matchPriority:=matchPriority, 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)
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?, matchPriority As Integer?, experimental As Boolean) As Threading.Tasks.Task
Return VerifyAtPositionAsync(code, position, ItemPartiallyWritten(expectedItemOrNull), expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, glyph:=glyph, matchPriority:=matchPriority, 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
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?, matchPriority 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
......@@ -76,15 +77,15 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Completion.Complet
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)
Await MyBase.VerifyWorkerAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, experimental:=experimental, glyph:=glyph, matchPriority:=matchPriority)
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)
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?, matchPriority As Integer?, experimental As Boolean) As Threading.Tasks.Task
Return VerifyAtEndOfFileAsync(code, position, String.Empty, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, glyph, matchPriority, 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)
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?, matchPriority As Integer?, experimental As Boolean) As Threading.Tasks.Task
Return VerifyAtEndOfFileAsync(code, position, ItemPartiallyWritten(expectedItemOrNull), expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, glyph, matchPriority, experimental)
End Function
Private Shared Function ItemPartiallyWritten(expectedItemOrNull As String) As String
......
......@@ -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, experimental As Boolean, glyph As Integer?, matchPriority As Integer?) As 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, experimental, matchPriority)
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, experimental:=False, matchPriority:=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, experimental:=False, matchPriority:=Nothing)
End Function
<WpfFact, Trait(Traits.Feature, Traits.Features.Completion)>
......
......@@ -1343,7 +1343,8 @@ 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, "10", Nothing, SourceCodeKind.Regular, usePreviousCharAsTrigger:=True, checkForAbsence:=False, glyph:=Nothing, experimental:=False, matchPriority:=Nothing)
End Function
<WorkItem(541235, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541235")>
......
......@@ -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, experimental As Boolean, glyph As Integer?, matchPriority As Integer?) As Task
Await VerifyAtPositionAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, glyph, matchPriority, experimental)
Await VerifyAtEndOfFileAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, glyph, matchPriority, experimental)
End Function
Private Async Function VerifyItemsExistAsync(markup As String, ParamArray items() As String) As Task
......
......@@ -58,6 +58,14 @@ public override async Task ProvideCompletionsAsync(CompletionContext context)
return;
}
// Don't show up within member access
// This previously worked because the type inferrer didn't work
// in member access expressions.
if (token.IsKind(SyntaxKind.DotToken))
{
return;
}
var typeInferenceService = document.GetLanguageService<ITypeInferenceService>();
Contract.ThrowIfNull(typeInferenceService, nameof(typeInferenceService));
......@@ -109,7 +117,7 @@ public override async Task ProvideCompletionsAsync(CompletionContext context)
span: context.DefaultItemSpan,
symbol: alias ?? type,
descriptionPosition: position,
preselect: true,
matchPriority: MatchPriority.Preselect,
rules: s_rules);
context.AddItem(item);
......
......@@ -239,7 +239,7 @@ private static CompletionItem Disambiguate(CompletionItem item, CompletionItem e
// the snippet item doesn't have its preselect bit set.
// We'll special case this by not preferring later items
// if they are snippets and the other candidate is preselected.
if (existingItem.Preselect && item.CompletionProvider is ISnippetCompletionProvider)
if (existingItem.MatchPriority != MatchPriority.Default && item.CompletionProvider is ISnippetCompletionProvider)
{
return existingItem;
}
......
......@@ -21,7 +21,7 @@ internal static class CommonCompletionItem
ImmutableArray<SymbolDisplayPart> description = default(ImmutableArray<SymbolDisplayPart>),
string sortText = null,
string filterText = null,
bool preselect = false,
int matchPriority = MatchPriority.Default,
bool showsWarningIcon = false,
bool shouldFormatOnCommit = false,
bool isArgumentName = false,
......@@ -54,7 +54,7 @@ internal static class CommonCompletionItem
}
rules = rules ?? CompletionItemRules.Default;
rules = rules.WithPreselect(preselect)
rules = rules.WithMatchPriority(matchPriority)
.WithFormatOnCommit(shouldFormatOnCommit);
return CompletionItem.Create(
......
......@@ -37,7 +37,7 @@ protected override CompletionItem GetBetterItem(CompletionItem item, CompletionI
// the snippet item doesn't have its preselect bit set.
// We'll special case this by not preferring later items
// if they are snippets and the other candidate is preselected.
if (existingItem.Rules.Preselect && IsSnippetItem(item))
if (existingItem.Rules.MatchPriority != MatchPriority.Default && IsSnippetItem(item))
{
return existingItem;
}
......
......@@ -20,7 +20,7 @@ public sealed class CompletionItemRules
commitCharacterRules: default(ImmutableArray<CharacterSetModificationRule>),
enterKeyRule: EnterKeyRule.Default,
formatOnCommit: false,
preselect: false);
matchPriority: Completion.MatchPriority.Default);
/// <summary>
/// Rules that modify the set of characters that can be typed to filter the list of completion items.
......@@ -45,20 +45,20 @@ public sealed class CompletionItemRules
/// <summary>
/// True if the related completion item should be initially selected.
/// </summary>
public bool Preselect { get; }
public int MatchPriority { get; }
private CompletionItemRules(
ImmutableArray<CharacterSetModificationRule> filterCharacterRules,
ImmutableArray<CharacterSetModificationRule> commitCharacterRules,
EnterKeyRule enterKeyRule,
bool formatOnCommit,
bool preselect)
int matchPriority)
{
this.FilterCharacterRules = filterCharacterRules.IsDefault ? ImmutableArray<CharacterSetModificationRule>.Empty : filterCharacterRules;
this.CommitCharacterRules = commitCharacterRules.IsDefault ? ImmutableArray<CharacterSetModificationRule>.Empty : commitCharacterRules;
this.EnterKeyRule = enterKeyRule;
this.FormatOnCommit = formatOnCommit;
this.Preselect = preselect;
this.MatchPriority = matchPriority;
}
/// <summary>
......@@ -68,26 +68,26 @@ public sealed class CompletionItemRules
/// <param name="commitCharacterRules">Rules about which keys typed caused the completion item to be committed.</param>
/// <param name="enterKeyRule">Rule about whether the enter key is passed through to the editor after the selected item has been committed.</param>
/// <param name="formatOnCommit">True if the modified text should be formatted automatically.</param>
/// <param name="preselect">True if the related completion item should be initially selected.</param>
/// <param name="matchPriority">True if the related completion item should be initially selected.</param>
/// <returns></returns>
public static CompletionItemRules Create(
ImmutableArray<CharacterSetModificationRule> filterCharacterRules = default(ImmutableArray<CharacterSetModificationRule>),
ImmutableArray<CharacterSetModificationRule> commitCharacterRules = default(ImmutableArray<CharacterSetModificationRule>),
EnterKeyRule enterKeyRule = EnterKeyRule.Default,
bool formatOnCommit = false,
bool preselect = false)
int matchPriority = Completion.MatchPriority.Default)
{
if (filterCharacterRules.IsDefaultOrEmpty
&& commitCharacterRules.IsDefaultOrEmpty
&& enterKeyRule == Default.EnterKeyRule
&& formatOnCommit == Default.FormatOnCommit
&& preselect == Default.Preselect)
&& matchPriority == Default.MatchPriority)
{
return Default;
}
else
{
return new CompletionItemRules(filterCharacterRules, commitCharacterRules, enterKeyRule, formatOnCommit, preselect);
return new CompletionItemRules(filterCharacterRules, commitCharacterRules, enterKeyRule, formatOnCommit, matchPriority);
}
}
......@@ -96,19 +96,19 @@ public sealed class CompletionItemRules
Optional<ImmutableArray<CharacterSetModificationRule>> commitRules = default(Optional<ImmutableArray<CharacterSetModificationRule>>),
Optional<EnterKeyRule> enterKeyRule = default(Optional<EnterKeyRule>),
Optional<bool> formatOnCommit = default(Optional<bool>),
Optional<bool> preselect = default(Optional<bool>))
Optional<int> matchPriority = default(Optional<int>))
{
var newFilterRules = filterRules.HasValue ? filterRules.Value : this.FilterCharacterRules;
var newCommitRules = commitRules.HasValue ? commitRules.Value : this.CommitCharacterRules;
var newEnterKeyRule = enterKeyRule.HasValue ? enterKeyRule.Value : this.EnterKeyRule;
var newFormatOnCommit = formatOnCommit.HasValue ? formatOnCommit.Value : this.FormatOnCommit;
var newPreselect = preselect.HasValue ? preselect.Value : this.Preselect;
var newPreselect = matchPriority.HasValue ? matchPriority.Value : this.MatchPriority;
if (newFilterRules == this.FilterCharacterRules &&
newCommitRules == this.CommitCharacterRules &&
newEnterKeyRule == this.EnterKeyRule &&
newFormatOnCommit == this.FormatOnCommit &&
newPreselect == this.Preselect)
newPreselect == this.MatchPriority)
{
return this;
}
......@@ -151,11 +151,11 @@ public CompletionItemRules WithFormatOnCommit(bool formatOnCommit)
}
/// <summary>
/// Creates a copy of this <see cref="CompletionItemRules"/> with the <see cref="Preselect"/> property changed.
/// Creates a copy of this <see cref="CompletionItemRules"/> with the <see cref="MatchPriority"/> property changed.
/// </summary>
public CompletionItemRules WithPreselect(bool preselect)
public CompletionItemRules WithMatchPriority(int matchPriority)
{
return this.With(preselect: preselect);
return this.With(matchPriority: matchPriority);
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.CodeAnalysis.Completion
{
/// <summary>
/// An additional hint to the matching algorithm that can
/// augment or override the existing text-based matching.
/// </summary>
public static class MatchPriority
{
/// <summary>
/// The matching algorithm should give this item no special treatment.
///
/// Ordinary <see cref="CompletionProvider"/>s typically specify this.
/// </summary>
public const int Default = 0;
/// <summary>
/// The matching algorithm will tend to prefer this item unless
/// a dramatically better text-based match is available.
///
/// With no filter text, this item (or the first item alphabeitcally
/// with this priority) should always be selected.
/// test
/// This is used for specific IDE scenarios like "Object creation preselection"
/// or "Enum preselection" or "Completion list tag preselection".
/// </summary>
public static readonly int Preselect = int.MaxValue / 2;
}
}
\ No newline at end of file
......@@ -78,7 +78,7 @@ protected virtual CompletionItem CreateItem(RecommendedKeyword keyword, TextSpan
description: keyword.DescriptionFactory(CancellationToken.None),
glyph: Glyph.Keyword,
tags: s_Tags,
preselect: keyword.ShouldPreselect);
matchPriority: MatchPriority.Default);
}
protected virtual async Task<IEnumerable<RecommendedKeyword>> RecommendKeywordsAsync(
......
......@@ -36,7 +36,7 @@ protected override CompletionItem CreateItem(string displayText, string insertio
descriptionPosition: position,
symbols: symbols,
supportedPlatforms: supportedPlatformData,
preselect: preselect,
matchPriority: MatchPriority.Preselect, // Always preselect
tags: s_Tags,
rules: GetCompletionItemRules(symbols, context));
}
......
......@@ -125,7 +125,7 @@ protected virtual CompletionItem CreateItem(string displayText, string insertion
descriptionPosition: position,
symbols: symbols,
supportedPlatforms: supportedPlatformData,
preselect: preselect,
matchPriority: preselect ? MatchPriority.Preselect : MatchPriority.Default,
rules: GetCompletionItemRules(symbols, context));
}
......@@ -220,7 +220,7 @@ private async Task<IEnumerable<CompletionItem>> GetItemsWorkerAsync(Document doc
var missingSymbolsMap = FindSymbolsMissingInLinkedContexts(unionedSymbolsList, contextAndSymbolLists);
var totalProjects = contextAndSymbolLists.Select(t => t.Item1.ProjectId).ToList();
return CreateItems(position, unionedSymbolsList, span, originatingContextMap, missingSymbolsMap, totalProjects, preselect: preselect);
return CreateItems(position, unionedSymbolsList, span, originatingContextMap, missingSymbolsMap, totalProjects, preselect);
}
protected virtual bool IsExclusive()
......
......@@ -26,7 +26,7 @@ internal static class SymbolCompletionItem
string insertionText = null,
Glyph? glyph = null,
string filterText = null,
bool preselect = false,
int? matchPriority = null,
SupportedPlatformData supportedPlatforms = null,
bool isArgumentName = false,
ImmutableDictionary<string, string> properties = null,
......@@ -58,7 +58,7 @@ internal static class SymbolCompletionItem
filterText: filterText ?? (displayText.Length > 0 && displayText[0] == '@' ? displayText : symbols[0].Name),
sortText: sortText ?? symbols[0].Name,
glyph: glyph ?? symbols[0].GetGlyph(),
preselect: preselect,
matchPriority: matchPriority.GetValueOrDefault(),
isArgumentName: isArgumentName,
showsWarningIcon: supportedPlatforms != null,
properties: props,
......@@ -78,7 +78,7 @@ internal static class SymbolCompletionItem
string insertionText = null,
Glyph? glyph = null,
string filterText = null,
bool preselect = false,
int matchPriority = MatchPriority.Default,
SupportedPlatformData supportedPlatforms = null,
bool isArgumentName = false,
ImmutableDictionary<string, string> properties = null,
......@@ -94,7 +94,7 @@ internal static class SymbolCompletionItem
insertionText: insertionText,
glyph: glyph,
filterText: filterText,
preselect: preselect,
matchPriority: matchPriority,
supportedPlatforms: supportedPlatforms,
isArgumentName: isArgumentName,
properties: properties,
......
......@@ -182,6 +182,7 @@
<Compile Include="Completion\ExportCompletionProviderAttribute.cs" />
<Compile Include="Completion\CompletionService.cs" />
<Compile Include="Completion\Providers\MemberInsertingCompletionItem.cs" />
<Compile Include="Completion\MatchPriority.cs" />
<Compile Include="Completion\Providers\UnionCompletionItemComparer.cs" />
<Compile Include="Completion\Providers\AbstractKeywordCompletionProvider.cs" />
<Compile Include="Completion\Providers\AbstractObjectCreationCompletionProvider.cs" />
......
......@@ -52,12 +52,12 @@ Microsoft.CodeAnalysis.Completion.CompletionItemRules.CommitCharacterRules.get -
Microsoft.CodeAnalysis.Completion.CompletionItemRules.EnterKeyRule.get -> Microsoft.CodeAnalysis.Completion.EnterKeyRule
Microsoft.CodeAnalysis.Completion.CompletionItemRules.FilterCharacterRules.get -> System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Completion.CharacterSetModificationRule>
Microsoft.CodeAnalysis.Completion.CompletionItemRules.FormatOnCommit.get -> bool
Microsoft.CodeAnalysis.Completion.CompletionItemRules.Preselect.get -> bool
Microsoft.CodeAnalysis.Completion.CompletionItemRules.MatchPriority.get -> int
Microsoft.CodeAnalysis.Completion.CompletionItemRules.WithCommitCharacterRules(System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Completion.CharacterSetModificationRule> commitCharacterRules) -> Microsoft.CodeAnalysis.Completion.CompletionItemRules
Microsoft.CodeAnalysis.Completion.CompletionItemRules.WithEnterKeyRule(Microsoft.CodeAnalysis.Completion.EnterKeyRule enterKeyRule) -> Microsoft.CodeAnalysis.Completion.CompletionItemRules
Microsoft.CodeAnalysis.Completion.CompletionItemRules.WithFilterCharacterRules(System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Completion.CharacterSetModificationRule> filterCharacterRules) -> Microsoft.CodeAnalysis.Completion.CompletionItemRules
Microsoft.CodeAnalysis.Completion.CompletionItemRules.WithFormatOnCommit(bool formatOnCommit) -> Microsoft.CodeAnalysis.Completion.CompletionItemRules
Microsoft.CodeAnalysis.Completion.CompletionItemRules.WithPreselect(bool preselect) -> Microsoft.CodeAnalysis.Completion.CompletionItemRules
Microsoft.CodeAnalysis.Completion.CompletionItemRules.WithMatchPriority(int matchPriority) -> Microsoft.CodeAnalysis.Completion.CompletionItemRules
Microsoft.CodeAnalysis.Completion.CompletionList
Microsoft.CodeAnalysis.Completion.CompletionList.DefaultSpan.get -> Microsoft.CodeAnalysis.Text.TextSpan
Microsoft.CodeAnalysis.Completion.CompletionList.Items.get -> System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Completion.CompletionItem>
......@@ -104,6 +104,7 @@ Microsoft.CodeAnalysis.Completion.ExportCompletionProviderAttribute.Language.get
Microsoft.CodeAnalysis.Completion.ExportCompletionProviderAttribute.Name.get -> string
Microsoft.CodeAnalysis.Completion.ExportCompletionProviderAttribute.Roles.get -> string[]
Microsoft.CodeAnalysis.Completion.ExportCompletionProviderAttribute.Roles.set -> void
Microsoft.CodeAnalysis.Completion.MatchPriority
Microsoft.CodeAnalysis.TaggedText
Microsoft.CodeAnalysis.TaggedText.Tag.get -> string
Microsoft.CodeAnalysis.TaggedText.TaggedText(string tag, string text) -> void
......@@ -148,6 +149,7 @@ const Microsoft.CodeAnalysis.Completion.CompletionTags.Snippet = "Snippet" -> st
const Microsoft.CodeAnalysis.Completion.CompletionTags.Structure = "Structure" -> string
const Microsoft.CodeAnalysis.Completion.CompletionTags.TypeParameter = "TypeParameter" -> string
const Microsoft.CodeAnalysis.Completion.CompletionTags.Warning = "Warning" -> string
const Microsoft.CodeAnalysis.Completion.MatchPriority.Default = 0 -> int
const Microsoft.CodeAnalysis.TextTags.Alias = "Alias" -> string
const Microsoft.CodeAnalysis.TextTags.AnonymousTypeIndicator = "AnonymousTypeIndicator" -> string
const Microsoft.CodeAnalysis.TextTags.Assembly = "Assembly" -> string
......@@ -189,7 +191,7 @@ static Microsoft.CodeAnalysis.Completion.CompletionChange.Create(System.Collecti
static Microsoft.CodeAnalysis.Completion.CompletionDescription.Create(System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.TaggedText> taggedParts) -> Microsoft.CodeAnalysis.Completion.CompletionDescription
static Microsoft.CodeAnalysis.Completion.CompletionDescription.FromText(string text) -> Microsoft.CodeAnalysis.Completion.CompletionDescription
static Microsoft.CodeAnalysis.Completion.CompletionItem.Create(string displayText, string filterText = null, string sortText = null, Microsoft.CodeAnalysis.Text.TextSpan span = default(Microsoft.CodeAnalysis.Text.TextSpan), System.Collections.Immutable.ImmutableDictionary<string, string> properties = null, System.Collections.Immutable.ImmutableArray<string> tags = default(System.Collections.Immutable.ImmutableArray<string>), Microsoft.CodeAnalysis.Completion.CompletionItemRules rules = null) -> Microsoft.CodeAnalysis.Completion.CompletionItem
static Microsoft.CodeAnalysis.Completion.CompletionItemRules.Create(System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Completion.CharacterSetModificationRule> filterCharacterRules = default(System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Completion.CharacterSetModificationRule>), System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Completion.CharacterSetModificationRule> commitCharacterRules = default(System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Completion.CharacterSetModificationRule>), Microsoft.CodeAnalysis.Completion.EnterKeyRule enterKeyRule = Microsoft.CodeAnalysis.Completion.EnterKeyRule.Default, bool formatOnCommit = false, bool preselect = false) -> Microsoft.CodeAnalysis.Completion.CompletionItemRules
static Microsoft.CodeAnalysis.Completion.CompletionItemRules.Create(System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Completion.CharacterSetModificationRule> filterCharacterRules = default(System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Completion.CharacterSetModificationRule>), System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Completion.CharacterSetModificationRule> commitCharacterRules = default(System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Completion.CharacterSetModificationRule>), Microsoft.CodeAnalysis.Completion.EnterKeyRule enterKeyRule = Microsoft.CodeAnalysis.Completion.EnterKeyRule.Default, bool formatOnCommit = false, int matchPriority = 0) -> Microsoft.CodeAnalysis.Completion.CompletionItemRules
static Microsoft.CodeAnalysis.Completion.CompletionItemRules.Default -> Microsoft.CodeAnalysis.Completion.CompletionItemRules
static Microsoft.CodeAnalysis.Completion.CompletionList.Create(Microsoft.CodeAnalysis.Text.TextSpan defaultSpan, System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Completion.CompletionItem> items, Microsoft.CodeAnalysis.Completion.CompletionRules rules = null, Microsoft.CodeAnalysis.Completion.CompletionItem suggestionModeItem = null) -> Microsoft.CodeAnalysis.Completion.CompletionList
static Microsoft.CodeAnalysis.Completion.CompletionRules.Create(bool dismissIfEmpty = false, bool dismissIfLastCharacterDeleted = false, System.Collections.Immutable.ImmutableArray<char> defaultCommitCharacters = default(System.Collections.Immutable.ImmutableArray<char>), Microsoft.CodeAnalysis.Completion.EnterKeyRule defaultEnterKeyRule = Microsoft.CodeAnalysis.Completion.EnterKeyRule.Default) -> Microsoft.CodeAnalysis.Completion.CompletionRules
......@@ -200,6 +202,7 @@ static readonly Microsoft.CodeAnalysis.Completion.CompletionDescription.Empty ->
static readonly Microsoft.CodeAnalysis.Completion.CompletionList.Empty -> Microsoft.CodeAnalysis.Completion.CompletionList
static readonly Microsoft.CodeAnalysis.Completion.CompletionRules.Default -> Microsoft.CodeAnalysis.Completion.CompletionRules
static readonly Microsoft.CodeAnalysis.Completion.CompletionTrigger.Default -> Microsoft.CodeAnalysis.Completion.CompletionTrigger
static readonly Microsoft.CodeAnalysis.Completion.MatchPriority.Preselect -> int
virtual Microsoft.CodeAnalysis.Completion.CompletionProvider.GetChangeAsync(Microsoft.CodeAnalysis.Document document, Microsoft.CodeAnalysis.Completion.CompletionItem item, char? commitKey, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task<Microsoft.CodeAnalysis.Completion.CompletionChange>
virtual Microsoft.CodeAnalysis.Completion.CompletionProvider.GetDescriptionAsync(Microsoft.CodeAnalysis.Document document, Microsoft.CodeAnalysis.Completion.CompletionItem item, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task<Microsoft.CodeAnalysis.Completion.CompletionDescription>
virtual Microsoft.CodeAnalysis.Completion.CompletionProvider.ShouldTriggerCompletion(Microsoft.CodeAnalysis.Text.SourceText text, int caretPosition, Microsoft.CodeAnalysis.Completion.CompletionTrigger trigger, Microsoft.CodeAnalysis.Options.OptionSet options) -> bool
......
......@@ -77,7 +77,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.Providers
descriptionPosition:=position,
sortText:=displayText,
glyph:=Glyph.EnumMember,
preselect:=preselect,
matchPriority:=MatchPriority.Preselect,
supportedPlatforms:=supportedPlatformData)
End Function
......
......@@ -33,7 +33,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.Providers
Return m.Kind = SymbolKind.Field AndAlso
DirectCast(m, IFieldSymbol).IsConst AndAlso
m.IsEditorBrowsable(hideAdvancedMembers, context.SemanticModel.Compilation)
End Function))
End Function).Concat(enumType))
End Function
......@@ -58,7 +58,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.Providers
Dim otherInstances = otherSymbols.Where(Function(s) enumType Is GetTypeFromSymbol(s))
Return Task.FromResult(otherInstances.Concat(enumType))
Return Task.FromResult(otherInstances)
End Function
Friend Overrides Function IsInsertionTrigger(text As SourceText, characterPosition As Integer, options As OptionSet) As Boolean
......@@ -109,17 +109,17 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.Providers
Return Await VisualBasicSyntaxContext.CreateContextAsync(document.Project.Solution.Workspace, semanticModel, position, cancellationToken).ConfigureAwait(False)
End Function
Protected Overrides Function CreateItem(displayText As String, insertionText As String, position As Integer, symbols As List(Of ISymbol), context As AbstractSyntaxContext, textChangeSpan As TextSpan, preselect As Boolean, supportedPlatformData As SupportedPlatformData) As CompletionItem
Protected Overrides Function CreateItem(displayText As String, insertionText As String, position As Integer, symbols As List(Of ISymbol), context As AbstractSyntaxContext, span As TextSpan, preselect As Boolean, supportedPlatformData As SupportedPlatformData) As CompletionItem
Return SymbolCompletionItem.Create(
displayText:=displayText,
insertionText:=insertionText,
filterText:=GetFilterText(symbols(0), displayText, context),
span:=textChangeSpan,
span:=span,
symbols:=symbols,
contextPosition:=context.Position,
descriptionPosition:=position,
sortText:=insertionText,
preselect:=preselect,
matchPriority:=MatchPriority.Preselect,
supportedPlatforms:=supportedPlatformData,
rules:=GetCompletionItemRules(symbols, context))
End Function
......
......@@ -86,8 +86,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion
Protected Overrides Function GetBetterItem(item As CompletionItem, existingItem As CompletionItem) As CompletionItem
' If one Is a keyword, And the other Is some other item that inserts the same text as the keyword,
' keep the keyword (VB only)
If IsKeywordItem(existingItem) Then
' keep the keyword (VB only), unless the other item is preselected
If IsKeywordItem(existingItem) AndAlso existingItem.Rules.MatchPriority >= item.Rules.MatchPriority Then
Return existingItem
End If
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册