Files
sdk/pkg/analysis_server/test/lsp/completion.dart
T
Danny Tuppeny 80fb1a56db [analysis_server] Add shared protocol.dart file for LSP
In an upcoming change some types will between these files. To reduce the size of that (already very large) CL and because the distinction between spec-generated/custom-generated types was unnecessary anyway, this adds a single import for LSP protocol-related types.

Change-Id: I322447d6c979538c12014d87875176e1bf2adca7
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/244244
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
2022-05-11 15:28:35 +00:00

111 lines
3.6 KiB
Dart

// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/lsp_protocol/protocol.dart';
import 'package:test/test.dart';
import 'server_abstract.dart';
mixin CompletionTestMixin on AbstractLspAnalysisServerTest {
/// The last set of completion results fetched.
List<CompletionItem> completionResults = [];
int sortTextSorter(CompletionItem item1, CompletionItem item2) =>
(item1.sortText ?? item1.label).compareTo(item2.sortText ?? item2.label);
Future<String?> verifyCompletions(
Uri fileUri,
String content, {
required List<String> expectCompletions,
String? applyEditsFor,
bool resolve = false,
String? expectedContent,
String? expectedContentIfInserting,
bool verifyInsertReplaceRanges = false,
bool openCloseFile = true,
}) async {
// If verifyInsertReplaceRanges is true, we need both expected contents.
assert(verifyInsertReplaceRanges == false ||
(expectedContent != null && expectedContentIfInserting != null));
if (!initialized) {
var textDocCapabilities =
withCompletionItemSnippetSupport(emptyTextDocumentClientCapabilities);
if (verifyInsertReplaceRanges) {
textDocCapabilities =
withCompletionItemInsertReplaceSupport(textDocCapabilities);
}
await initialize(textDocumentCapabilities: textDocCapabilities);
}
if (openCloseFile) {
await openFile(fileUri, withoutMarkers(content));
}
completionResults =
await getCompletion(fileUri, positionFromMarker(content));
if (openCloseFile) {
await closeFile(fileUri);
}
// Sort the completions by sortText and filter to those we expect, so the ordering
// can be compared.
final sortedResults = completionResults
.where((r) => expectCompletions.contains(r.label))
.toList()
..sort(sortTextSorter);
expect(sortedResults.map((item) => item.label), equals(expectCompletions));
// Check the edits apply correctly.
if (applyEditsFor != null) {
var item = completionResults.singleWhere((c) => c.label == applyEditsFor);
final insertFormat = item.insertTextFormat;
if (resolve) {
item = await resolveCompletion(item);
}
String updatedContent;
if (verifyInsertReplaceRanges &&
expectedContent != expectedContentIfInserting) {
// Replacing.
updatedContent = applyTextEdits(
withoutMarkers(content),
[textEditForReplace(item.textEdit!)],
);
expect(
withCaret(updatedContent, insertFormat), equals(expectedContent));
// Inserting.
final inserted = applyTextEdits(
withoutMarkers(content),
[textEditForInsert(item.textEdit!)],
);
expect(withCaret(inserted, insertFormat),
equals(expectedContentIfInserting));
} else {
updatedContent = applyTextEdits(
withoutMarkers(content),
[toTextEdit(item.textEdit!)],
);
if (expectedContent != null) {
expect(
withCaret(updatedContent, insertFormat), equals(expectedContent));
}
}
return updatedContent;
}
return null;
}
/// Replaces the LSP snippet placeholder '$0' with '^' for easier verifying
/// of the cursor position in completions.
String withCaret(String contents, InsertTextFormat? format) =>
format == InsertTextFormat.Snippet
? contents.replaceFirst(r'$0', '^')
: contents;
}