mirror of
https://github.com/dart-lang/sdk
synced 2024-09-19 21:11:40 +00:00
20b560226e
Change-Id: I1c2a4f15dee607a0a6241dfaf2d764a7d284389b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/241510 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Reviewed-by: Samuel Rawlins <srawlins@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
152 lines
4.9 KiB
Dart
152 lines
4.9 KiB
Dart
// Copyright (c) 2014, 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 'dart:async';
|
|
|
|
import 'package:analysis_server/protocol/protocol.dart';
|
|
import 'package:analysis_server/protocol/protocol_constants.dart';
|
|
import 'package:analysis_server/protocol/protocol_generated.dart';
|
|
import 'package:analyzer_plugin/protocol/protocol_common.dart';
|
|
import 'package:test/test.dart';
|
|
|
|
import 'analysis_server_base.dart';
|
|
import 'constants.dart';
|
|
|
|
class AbstractCompletionDomainTest extends PubPackageAnalysisServerTest {
|
|
late String completionId;
|
|
late int completionOffset; // TODO(scheglov) remove it
|
|
int? replacementOffset;
|
|
late int replacementLength;
|
|
Map<String, Completer<void>> receivedSuggestionsCompleters = {};
|
|
List<CompletionSuggestion> suggestions = [];
|
|
bool suggestionsDone = false;
|
|
Map<String, List<CompletionSuggestion>> allSuggestions = {};
|
|
|
|
void assertHasResult(CompletionSuggestionKind kind, String completion,
|
|
{bool isDeprecated = false,
|
|
bool isPotential = false,
|
|
int? selectionOffset,
|
|
int? replacementOffset,
|
|
int? replacementLength,
|
|
ElementKind? elementKind}) {
|
|
CompletionSuggestion? cs;
|
|
for (var s in suggestions) {
|
|
if (elementKind != null && s.element?.kind != elementKind) {
|
|
return;
|
|
}
|
|
if (s.completion == completion) {
|
|
if (cs == null) {
|
|
cs = s;
|
|
} else {
|
|
fail('expected exactly one $completion but found > 1');
|
|
}
|
|
}
|
|
}
|
|
if (cs == null) {
|
|
var completions = suggestions.map((s) => s.completion).toList();
|
|
|
|
var expectationText = '"$completion"';
|
|
if (elementKind != null) {
|
|
expectationText += ' ($elementKind)';
|
|
}
|
|
|
|
fail('expected $expectationText, but found\n $completions');
|
|
}
|
|
var suggestion = cs;
|
|
expect(suggestion.kind, equals(kind));
|
|
expect(suggestion.selectionOffset, selectionOffset ?? completion.length);
|
|
expect(suggestion.selectionLength, equals(0));
|
|
expect(suggestion.replacementOffset, equals(replacementOffset));
|
|
expect(suggestion.replacementLength, equals(replacementLength));
|
|
expect(suggestion.isDeprecated, equals(isDeprecated));
|
|
expect(suggestion.isPotential, equals(isPotential));
|
|
}
|
|
|
|
void assertNoResult(String completion, {ElementKind? elementKind}) {
|
|
if (suggestions.any((cs) =>
|
|
cs.completion == completion &&
|
|
(elementKind == null || cs.element?.kind == elementKind))) {
|
|
fail('did not expect completion: $completion');
|
|
}
|
|
}
|
|
|
|
void assertValidId(String id) {
|
|
expect(id, isNotNull);
|
|
expect(id.isNotEmpty, isTrue);
|
|
}
|
|
|
|
Future<void> getCodeSuggestions({
|
|
required String path,
|
|
required String content,
|
|
}) async {
|
|
completionOffset = content.indexOf('^');
|
|
expect(completionOffset, isNot(equals(-1)), reason: 'missing ^');
|
|
|
|
var nextOffset = content.indexOf('^', completionOffset + 1);
|
|
expect(nextOffset, equals(-1), reason: 'too many ^');
|
|
|
|
newFile(
|
|
path,
|
|
content.substring(0, completionOffset) +
|
|
content.substring(completionOffset + 1),
|
|
);
|
|
|
|
return await getSuggestions(
|
|
path: path,
|
|
completionOffset: completionOffset,
|
|
);
|
|
}
|
|
|
|
Future<void> getSuggestions({
|
|
required String path,
|
|
required int completionOffset,
|
|
}) async {
|
|
var request =
|
|
CompletionGetSuggestionsParams(path, completionOffset).toRequest('0');
|
|
var response = await handleSuccessfulRequest(request);
|
|
var result = CompletionGetSuggestionsResult.fromResponse(response);
|
|
completionId = result.id;
|
|
assertValidId(completionId);
|
|
await _getResultsCompleter(completionId).future;
|
|
expect(suggestionsDone, isTrue);
|
|
}
|
|
|
|
Future<void> getTestCodeSuggestions(String content) {
|
|
return getCodeSuggestions(
|
|
path: testFile.path,
|
|
content: content,
|
|
);
|
|
}
|
|
|
|
@override
|
|
Future<void> processNotification(Notification notification) async {
|
|
if (notification.event == COMPLETION_RESULTS) {
|
|
var params = CompletionResultsParams.fromNotification(notification);
|
|
var id = params.id;
|
|
assertValidId(id);
|
|
replacementOffset = params.replacementOffset;
|
|
replacementLength = params.replacementLength;
|
|
suggestionsDone = params.isLast;
|
|
expect(suggestionsDone, isNotNull);
|
|
suggestions = params.results;
|
|
expect(allSuggestions.containsKey(id), isFalse);
|
|
allSuggestions[id] = params.results;
|
|
_getResultsCompleter(id).complete(null);
|
|
} else if (notification.event == SERVER_NOTIFICATION_ERROR) {
|
|
fail('server error: ${notification.toJson()}');
|
|
}
|
|
}
|
|
|
|
@override
|
|
Future<void> setUp() async {
|
|
super.setUp();
|
|
await setRoots(included: [workspaceRootPath], excluded: []);
|
|
}
|
|
|
|
Completer<void> _getResultsCompleter(String id) {
|
|
return receivedSuggestionsCompleters.putIfAbsent(
|
|
id, () => Completer<void>());
|
|
}
|
|
}
|