Skip to content
This repository was archived by the owner on Nov 4, 2024. It is now read-only.

Commit cc4700d

Browse files
authored
Fix invalid insertTextFormat in CompletionItem instances (microsoft#344)
* fix invalid insertTextFormat in CompletionItem instances * check insertTextFormat in AssertCompletion, defaulted to PlainText * only check items which are in contains for format matching, not all
1 parent 4281c6a commit cc4700d

File tree

4 files changed

+39
-16
lines changed

4 files changed

+39
-16
lines changed

src/Analysis/Engine/Test/CompletionTests.cs

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,8 @@ class oar(list):
243243
var completions = await server.SendCompletion(uri, 2, 8);
244244

245245
completions.Should().HaveItem("append")
246-
.Which.Should().HaveInsertText($"append(self, value):{Environment.NewLine} return super(oar, self).append(value)");
246+
.Which.Should().HaveInsertText($"append(self, value):{Environment.NewLine} return super(oar, self).append(value)")
247+
.And.HaveInsertTextFormat(InsertTextFormat.PlainText);
247248
}
248249

249250
[DataRow(PythonLanguageVersion.V36, "value")]
@@ -259,7 +260,8 @@ class oar(list):
259260
var completions = await server.SendCompletion(uri, 2, 8);
260261

261262
completions.Should().HaveItem("append")
262-
.Which.Should().HaveInsertText($"append(self, {parameterName}):{Environment.NewLine} return super().append({parameterName})");
263+
.Which.Should().HaveInsertText($"append(self, {parameterName}):{Environment.NewLine} return super().append({parameterName})")
264+
.And.HaveInsertTextFormat(InsertTextFormat.PlainText);
263265
}
264266

265267
[ServerTestMethod(LatestAvailable2X = true), Priority(0)]
@@ -417,7 +419,8 @@ public async Task AddBracketsEnabled(Server server, string code, int row, int ch
417419
var completion = await server.SendCompletion(uri, row, character);
418420

419421
completion.Should().HaveItem(expectedLabel)
420-
.Which.Should().HaveInsertText(expectedInsertText);
422+
.Which.Should().HaveInsertText(expectedInsertText)
423+
.And.HaveInsertTextFormat(InsertTextFormat.Snippet);
421424
}
422425

423426
[DataRow(PythonLanguageMajorVersion.LatestV2, "foo(self):{0} return super(B, self).foo()")]
@@ -438,7 +441,8 @@ class B(A):
438441
var completion = await server.SendCompletion(uri, 6, 9);
439442

440443
completion.Should().HaveItem("foo")
441-
.Which.Should().HaveInsertText(expectedInsertText);
444+
.Which.Should().HaveInsertText(expectedInsertText)
445+
.And.HaveInsertTextFormat(InsertTextFormat.PlainText);
442446
}
443447

444448
[TestMethod, Priority(0)]
@@ -499,7 +503,8 @@ public async Task Completion_PackageRelativeImport(Server server) {
499503
var completion = await server.SendCompletion(uri, 0, 22);
500504

501505
completion.Should().HaveItem("right")
502-
.Which.Should().HaveInsertText("right");
506+
.Which.Should().HaveInsertText("right")
507+
.And.HaveInsertTextFormat(InsertTextFormat.PlainText);
503508
}
504509

505510
[DataRow(true)]
@@ -1008,7 +1013,7 @@ public async Task MultiPartDocument() {
10081013
public async Task WithWhitespaceAroundDot() {
10091014
using (var s = await CreateServerAsync()) {
10101015
var u = await s.OpenDefaultDocumentAndGetUriAsync("import sys\nsys . version\n");
1011-
await AssertCompletion(s, u, new[] { "argv" }, null, new SourceLocation(2, 7),
1016+
await AssertCompletion(s, u, new[] { "argv" }, null, new SourceLocation(2, 7),
10121017
new CompletionContext { triggerCharacter = ".", triggerKind = CompletionTriggerKind.TriggerCharacter });
10131018
}
10141019
}
@@ -1029,7 +1034,7 @@ public async Task MarkupKindValid() {
10291034
}
10301035
}
10311036

1032-
private static async Task AssertCompletion(Server s, Uri uri, IReadOnlyCollection<string> contains, IReadOnlyCollection<string> excludes, Position? position = null, CompletionContext? context = null, Func<CompletionItem, string> cmpKey = null, string expr = null, Range? applicableSpan = null) {
1037+
private static async Task AssertCompletion(Server s, Uri uri, IReadOnlyCollection<string> contains, IReadOnlyCollection<string> excludes, Position? position = null, CompletionContext? context = null, Func<CompletionItem, string> cmpKey = null, string expr = null, Range? applicableSpan = null, InsertTextFormat? allFormat = InsertTextFormat.PlainText) {
10331038
await s.WaitForCompleteAnalysisAsync(CancellationToken.None);
10341039
var res = await s.Completion(new CompletionParams {
10351040
textDocument = new TextDocumentIdentifier { uri = uri },
@@ -1040,10 +1045,14 @@ private static async Task AssertCompletion(Server s, Uri uri, IReadOnlyCollectio
10401045
DumpDetails(res);
10411046

10421047
cmpKey = cmpKey ?? (c => c.insertText);
1043-
var items = res.items?.Select(cmpKey).ToList() ?? new List<string>();
1048+
var items = res.items?.Select(i => (cmpKey(i), i.insertTextFormat)).ToList() ?? new List<(string, InsertTextFormat)>();
10441049

10451050
if (contains != null && contains.Any()) {
1046-
items.Should().Contain(contains);
1051+
items.Select(i => i.Item1).Should().Contain(contains);
1052+
1053+
if (allFormat != null) {
1054+
items.Where(i => contains.Contains(i.Item1)).Select(i => i.Item2).Should().AllBeEquivalentTo(allFormat);
1055+
}
10471056
}
10481057

10491058
if (excludes != null && excludes.Any()) {
@@ -1119,4 +1128,4 @@ await s.DidOpenTextDocument(new DidOpenTextDocumentParams {
11191128
return uri;
11201129
}
11211130
}
1122-
}
1131+
}

src/Analysis/Engine/Test/FluentAssertions/CompletionItemAssertions.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,15 @@ public AndConstraint<CompletionItemAssertions> HaveInsertText(string insertText,
4040
return new AndConstraint<CompletionItemAssertions>(this);
4141
}
4242

43+
[CustomAssertion]
44+
public AndConstraint<CompletionItemAssertions> HaveInsertTextFormat(InsertTextFormat insertTextFormat, string because = "", params object[] reasonArgs) {
45+
Execute.Assertion.ForCondition(Subject.insertTextFormat == insertTextFormat)
46+
.BecauseOf(because, reasonArgs)
47+
.FailWith($"Expected '{Subject.label}' completion to have insert text format '{insertTextFormat}'{{reason}}, but it has '{Subject.insertTextFormat}'");
48+
49+
return new AndConstraint<CompletionItemAssertions>(this);
50+
}
51+
4352
[CustomAssertion]
4453
public AndConstraint<CompletionItemAssertions> HaveDocumentation(string documentation, string because = "", params object[] reasonArgs) {
4554
Execute.Assertion.BecauseOf(because, reasonArgs)
@@ -51,4 +60,4 @@ public AndConstraint<CompletionItemAssertions> HaveDocumentation(string document
5160
return new AndConstraint<CompletionItemAssertions>(this);
5261
}
5362
}
54-
}
63+
}

src/LanguageServer/Impl/Implementation/CompletionAnalysis.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,8 @@ public IEnumerable<CompletionItem> GetCompletions() {
200200
return null;
201201
}
202202

203-
return addMetadataArg
204-
? GetCompletionsFromTopLevel().Append(MetadataArgCompletion)
203+
return addMetadataArg
204+
? GetCompletionsFromTopLevel().Append(MetadataArgCompletion)
205205
: GetCompletionsFromTopLevel();
206206

207207
case ForStatement forStatement when TryGetCompletionsInForStatement(forStatement, out var result):
@@ -269,7 +269,7 @@ private IEnumerable<CompletionItem> GetModules(string[] names, bool includeMembe
269269
return GetModules();
270270
}
271271

272-
private IEnumerable<CompletionItem> GetModules()
272+
private IEnumerable<CompletionItem> GetModules()
273273
=> Analysis.ProjectState.GetModules().Select(ToCompletionItem);
274274

275275
private IEnumerable<CompletionItem> GetModulesFromNode(DottedName name, bool includeMembers = false) => GetModules(GetNamesFromDottedName(name), includeMembers);
@@ -410,6 +410,7 @@ private CompletionItem ToOverrideCompletionItem(IOverloadResult o, ClassDefiniti
410410
return new CompletionItem {
411411
label = o.Name,
412412
insertText = MakeOverrideCompletionString(indent, o, cd.Name),
413+
insertTextFormat = InsertTextFormat.PlainText,
413414
kind = CompletionItemKind.Method
414415
};
415416
}
@@ -799,10 +800,11 @@ private CompletionItem ToCompletionItem(IMemberResult m) {
799800

800801
var doc = _textBuilder.GetDocumentation(m.Values, string.Empty);
801802
var kind = ToCompletionItemKind(m.MemberType);
802-
803+
803804
var res = new CompletionItem {
804805
label = m.Name,
805806
insertText = completion,
807+
insertTextFormat = InsertTextFormat.PlainText,
806808
documentation = string.IsNullOrWhiteSpace(doc) ? null : new MarkupContent {
807809
kind = _textBuilder.DisplayOptions.preferredFormat,
808810
value = doc
@@ -825,6 +827,7 @@ private static CompletionItem ToCompletionItem(string text, PythonMemberType typ
825827
return new CompletionItem {
826828
label = label ?? text,
827829
insertText = text,
830+
insertTextFormat = InsertTextFormat.PlainText,
828831
// Place regular items first, advanced entries last
829832
sortText = char.IsLetter(text, 0) ? "1" : "2",
830833
kind = ToCompletionItemKind(type),
@@ -976,4 +979,4 @@ private IEnumerable<Token> ReadExpressionTokens(IEnumerable<KeyValuePair<IndexSp
976979
return exprTokens;
977980
}
978981
}
979-
}
982+
}

src/LanguageServer/Impl/Implementation/Server.Completion.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ private bool HandleOldStyleCompletionExtension(ModuleAnalysis analysis, PythonAs
146146
filterText = x.filterText,
147147
preselect = x.preselect,
148148
insertText = x.insertText,
149+
insertTextFormat = (PythonTools.Analysis.LanguageServer.InsertTextFormat)x.insertTextFormat,
149150
}).ToArray()
150151
};
151152

@@ -169,6 +170,7 @@ private bool HandleOldStyleCompletionExtension(ModuleAnalysis analysis, PythonAs
169170
filterText = x.filterText,
170171
preselect = x.preselect,
171172
insertText = x.insertText,
173+
insertTextFormat = (InsertTextFormat)x.insertTextFormat,
172174
textEdit = x.textEdit.HasValue
173175
? new TextEdit {
174176
range = new Range {

0 commit comments

Comments
 (0)