blob: dddf75ec3986f8a17731cbb05d7b86c00b9307e2 [file] [log] [blame]
// 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.services.completion.suggestion;
import 'dart:async';
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/protocol.dart';
import 'package:analysis_server/src/provisional/completion/completion_core.dart'
show CompletionRequest, CompletionResult;
import 'package:analysis_server/src/services/completion/completion_manager.dart';
import 'package:analysis_server/src/services/completion/dart_completion_manager.dart';
import 'package:analysis_server/src/services/index/index.dart';
import 'package:analysis_server/src/services/index/local_memory_index.dart';
import 'package:analysis_server/src/services/search/search_engine.dart';
import 'package:analysis_server/src/services/search/search_engine_internal.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'package:unittest/unittest.dart';
import '../../abstract_single_unit.dart';
import '../../operation/operation_queue_test.dart';
import '../../utils.dart';
main() {
initializeTestEnvironment();
defineReflectiveTests(DartCompletionManagerTest);
}
/**
* Returns a [Future] that completes after pumping the event queue [times]
* times. By default, this should pump the event queue enough times to allow
* any code to run, as long as it's not waiting on some external event.
*/
Future pumpEventQueue([int times = 20]) {
if (times == 0) return new Future.value();
// We use a delayed future to allow microtask events to finish. The
// Future.value or Future() constructors use scheduleMicrotask themselves and
// would therefore not wait for microtask callbacks that are scheduled after
// invoking this method.
return new Future.delayed(Duration.ZERO, () => pumpEventQueue(times - 1));
}
@reflectiveTest
class DartCompletionManagerTest extends AbstractSingleUnitTest {
Index index;
SearchEngineImpl searchEngine;
Source source;
DartCompletionManager manager;
MockCompletionContributor contributor1;
MockCompletionContributor contributor2;
CompletionSuggestion suggestion1;
CompletionSuggestion suggestion2;
bool _continuePerformingAnalysis = true;
void resolveLibrary() {
context.resolveCompilationUnit(
source, context.computeLibraryElement(source));
}
@override
void setUp() {
super.setUp();
index = createLocalMemoryIndex();
searchEngine = new SearchEngineImpl(index);
source = addSource('/does/not/exist.dart', '');
manager = new DartCompletionManager.create(context, searchEngine, source);
suggestion1 = new CompletionSuggestion(CompletionSuggestionKind.INVOCATION,
DART_RELEVANCE_DEFAULT, "suggestion1", 1, 1, false, false);
suggestion2 = new CompletionSuggestion(CompletionSuggestionKind.IDENTIFIER,
DART_RELEVANCE_DEFAULT, "suggestion2", 2, 2, false, false);
new Future(_performAnalysis);
}
@override
void tearDown() {
_continuePerformingAnalysis = false;
}
test_compute_fastAndFull() {
contributor1 = new MockCompletionContributor(suggestion1, null);
contributor2 = new MockCompletionContributor(null, suggestion2);
manager.contributors = [contributor1, contributor2];
int count = 0;
bool done = false;
AnalysisServer server = new AnalysisServerMock(searchEngine: searchEngine);
CompletionRequest completionRequest =
new CompletionRequestImpl(server, context, source, 0);
manager.results(completionRequest).listen((CompletionResult r) {
bool isLast = r is CompletionResultImpl ? r.isLast : true;
switch (++count) {
case 1:
contributor1.assertCalls(context, source, 0, searchEngine);
expect(contributor1.fastCount, equals(1));
expect(contributor1.fullCount, equals(0));
contributor2.assertCalls(context, source, 0, searchEngine);
expect(contributor2.fastCount, equals(1));
expect(contributor2.fullCount, equals(1));
expect(isLast, isTrue);
expect(r.suggestions, hasLength(2));
expect(r.suggestions, contains(suggestion1));
expect(r.suggestions, contains(suggestion2));
resolveLibrary();
break;
default:
fail('unexpected');
}
}, onDone: () {
done = true;
// There is only one notification
expect(count, equals(1));
});
return pumpEventQueue().then((_) {
expect(done, isTrue);
});
}
test_compute_fastOnly() {
contributor1 = new MockCompletionContributor(suggestion1, null);
contributor2 = new MockCompletionContributor(suggestion2, null);
manager.contributors = [contributor1, contributor2];
int count = 0;
bool done = false;
AnalysisServer server = new AnalysisServerMock(searchEngine: searchEngine);
CompletionRequest completionRequest =
new CompletionRequestImpl(server, context, source, 0);
manager.results(completionRequest).listen((CompletionResult r) {
bool isLast = r is CompletionResultImpl ? r.isLast : true;
switch (++count) {
case 1:
contributor1.assertCalls(context, source, 0, searchEngine);
expect(contributor1.fastCount, equals(1));
expect(contributor1.fullCount, equals(0));
contributor2.assertCalls(context, source, 0, searchEngine);
expect(contributor2.fastCount, equals(1));
expect(contributor2.fullCount, equals(0));
expect(isLast, isTrue);
expect(r.suggestions, hasLength(2));
expect(r.suggestions, contains(suggestion1));
expect(r.suggestions, contains(suggestion2));
break;
default:
fail('unexpected');
}
}, onDone: () {
done = true;
expect(count, equals(1));
});
return pumpEventQueue().then((_) {
expect(done, isTrue);
});
}
void _performAnalysis() {
if (!_continuePerformingAnalysis) {
return;
}
context.performAnalysisTask();
new Future(_performAnalysis);
}
}
class MockCompletionContributor extends DartCompletionContributor {
final CompletionSuggestion fastSuggestion;
final CompletionSuggestion fullSuggestion;
int fastCount = 0;
int fullCount = 0;
DartCompletionRequest request;
MockCompletionContributor(this.fastSuggestion, this.fullSuggestion);
assertCalls(AnalysisContext context, Source source, int offset, SearchEngine searchEngine) {
expect(request.context, equals(context));
expect(request.source, equals(source));
expect(request.offset, equals(offset));
expect(request.searchEngine, equals(searchEngine));
}
assertFull(int fullCount) {
expect(this.fastCount, equals(1));
expect(this.fullCount, equals(fullCount));
}
@override
bool computeFast(DartCompletionRequest request) {
this.request = request;
fastCount++;
if (fastSuggestion != null) {
request.addSuggestion(fastSuggestion);
}
return fastSuggestion != null;
}
@override
Future<bool> computeFull(DartCompletionRequest request) {
this.request = request;
fullCount++;
if (fullSuggestion != null) {
request.addSuggestion(fullSuggestion);
}
return new Future.value(fullSuggestion != null);
}
}