Files
sdk/pkg/analysis_server/test/domain_completion_util.dart
T
Konstantin Shcheglov fc30904a39 Completion with the new analysis driver.
It works for top-levels, fields, locals, prefixed expressions.

Integration is not the most efficient - we resolve the full unit.
It works fine for files with about 1000 lines, about 50-70 ms.

We could slightly improve timing if we prioritize completion over
navigation and highlight notifications, which are currently prepared
and sent before completion.

In giant files like src/dart/element/element.dart, about 8500 lines,
it takes about 400 ms from typing to receiving completion. The theoretical
bottom bound for such files is about 70 ms - time that it required to
parse, create unlinked bundle, ensure that the API signature is the
same, load linked bundles and prepare to resynthesize. On top of this
goes any time required to resolve a single method and completion itself.

R=brianwilkerson@google.com, paulberry@google.com
BUG=

Review URL: https://codereview.chromium.org/2478963002 .
2016-11-06 10:45:46 -08:00

129 lines
4.3 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.
library test.domain.completion;
import 'dart:async';
import 'package:analysis_server/plugin/protocol/protocol.dart';
import 'package:analysis_server/src/constants.dart';
import 'package:analysis_server/src/domain_completion.dart';
import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
import 'package:analysis_server/src/services/index/index.dart';
import 'package:test/test.dart';
import 'analysis_abstract.dart';
class AbstractCompletionDomainTest extends AbstractAnalysisTest {
String completionId;
int completionOffset;
int replacementOffset;
int replacementLength;
Map<String, Completer<Null>> receivedSuggestionsCompleters = {};
List<CompletionSuggestion> suggestions = [];
bool suggestionsDone = false;
Map<String, List<CompletionSuggestion>> allSuggestions = {};
String addTestFile(String content, {int offset}) {
completionOffset = content.indexOf('^');
if (offset != null) {
expect(completionOffset, -1, reason: 'cannot supply offset and ^');
completionOffset = offset;
return super.addTestFile(content);
}
expect(completionOffset, isNot(equals(-1)), reason: 'missing ^');
int nextOffset = content.indexOf('^', completionOffset + 1);
expect(nextOffset, equals(-1), reason: 'too many ^');
return super.addTestFile(content.substring(0, completionOffset) +
content.substring(completionOffset + 1));
}
void assertHasResult(CompletionSuggestionKind kind, String completion,
{int relevance: DART_RELEVANCE_DEFAULT,
bool isDeprecated: false,
bool isPotential: false,
int selectionOffset}) {
var cs;
suggestions.forEach((s) {
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();
fail('expected "$completion" but found\n $completions');
}
expect(cs.kind, equals(kind));
expect(cs.relevance, equals(relevance));
expect(cs.selectionOffset, selectionOffset ?? completion.length);
expect(cs.selectionLength, equals(0));
expect(cs.isDeprecated, equals(isDeprecated));
expect(cs.isPotential, equals(isPotential));
}
void assertNoResult(String completion) {
if (suggestions.any((cs) => cs.completion == completion)) {
fail('did not expect completion: $completion');
}
}
void assertValidId(String id) {
expect(id, isNotNull);
expect(id.isNotEmpty, isTrue);
}
@override
Index createIndex() {
return createMemoryIndex();
}
Future getSuggestions() async {
await waitForTasksFinished();
Request request =
new CompletionGetSuggestionsParams(testFile, completionOffset)
.toRequest('0');
Response response = await waitResponse(request);
var result = new CompletionGetSuggestionsResult.fromResponse(response);
completionId = result.id;
assertValidId(completionId);
await _getResultsCompleter(completionId).future;
expect(suggestionsDone, isTrue);
}
processNotification(Notification notification) async {
if (notification.event == COMPLETION_RESULTS) {
var params = new CompletionResultsParams.fromNotification(notification);
String 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_ERROR) {
fail('server error: ${notification.toJson()}');
}
}
@override
void setUp() {
super.setUp();
createProject();
handler = new CompletionDomainHandler(server);
}
Completer<Null> _getResultsCompleter(String id) {
return receivedSuggestionsCompleters.putIfAbsent(
id, () => new Completer<Null>());
}
}