Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(172)

Unified Diff: pkg/analysis_server/test/services/completion/dart/dart_completion_contributor_test.dart

Issue 1407273004: next step toward completion plugin API (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: address comments Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/analysis_server/test/services/completion/dart/dart_completion_contributor_test.dart
diff --git a/pkg/analysis_server/test/services/completion/dart/dart_completion_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/dart_completion_contributor_test.dart
new file mode 100644
index 0000000000000000000000000000000000000000..cb4c2181f604a9b98b9d016fbfcb91a2ef7e6c98
--- /dev/null
+++ b/pkg/analysis_server/test/services/completion/dart/dart_completion_contributor_test.dart
@@ -0,0 +1,225 @@
+// 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.contributor.dart;
+
+import 'dart:async';
+
+import 'package:analysis_server/plugin/protocol/protocol.dart' as protocol
+ show Element, ElementKind;
+import 'package:analysis_server/plugin/protocol/protocol.dart'
+ hide Element, ElementKind;
+import 'package:analysis_server/plugin/protocol/protocol.dart';
+import 'package:analysis_server/src/provisional/completion/completion_dart.dart'
+ show DartCompletionContributor, DartCompletionRequest;
+import 'package:analysis_server/src/provisional/completion/dart/completion_target.dart';
+import 'package:analysis_server/src/services/completion/completion_core.dart'
+ show CompletionRequestImpl;
+import 'package:analysis_server/src/services/completion/completion_dart.dart'
+ show DartCompletionRequestImpl;
+import 'package:analysis_server/src/services/completion/dart/dart_completion_manager.dart';
+import 'package:analysis_server/src/services/completion/dart/reference_contributor.dart';
+import 'package:analysis_server/src/services/completion/dart_completion_manager.dart'
+ show DART_RELEVANCE_DEFAULT, DART_RELEVANCE_LOW;
+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_internal.dart';
+import 'package:analyzer/src/cancelable_future.dart';
+import 'package:analyzer/src/context/context.dart';
+import 'package:analyzer/src/generated/ast.dart';
+import 'package:analyzer/src/generated/engine.dart' hide AnalysisContextImpl;
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/task/dart.dart';
+import 'package:analyzer/task/dart.dart';
+import 'package:analyzer/task/model.dart';
+import 'package:unittest/unittest.dart';
+
+import '../../../abstract_context.dart';
+
+int suggestionComparator(CompletionSuggestion s1, CompletionSuggestion s2) {
+ String c1 = s1.completion.toLowerCase();
+ String c2 = s2.completion.toLowerCase();
+ return c1.compareTo(c2);
+}
+
+abstract class DartCompletionContributorTest extends AbstractContextTest {
+ Index index;
+ SearchEngineImpl searchEngine;
+ String testFile = '/completionTest.dart';
+ Source testSource;
+ int completionOffset;
+ DartCompletionContributor contributor;
+ DartCompletionRequest request;
+ List<CompletionSuggestion> suggestions;
+
+ void addTestSource(String content) {
+ expect(completionOffset, isNull, reason: 'Call addTestUnit exactly once');
+ completionOffset = content.indexOf('^');
+ expect(completionOffset, isNot(equals(-1)), reason: 'missing ^');
+ int nextOffset = content.indexOf('^', completionOffset + 1);
+ expect(nextOffset, equals(-1), reason: 'too many ^');
+ content = content.substring(0, completionOffset) +
+ content.substring(completionOffset + 1);
+ testSource = addSource(testFile, content);
+ }
+
+ void assertHasParameterInfo(CompletionSuggestion suggestion) {
+ expect(suggestion.parameterNames, isNotNull);
+ expect(suggestion.parameterTypes, isNotNull);
+ expect(suggestion.parameterNames.length, suggestion.parameterTypes.length);
+ expect(suggestion.requiredParameterCount,
+ lessThanOrEqualTo(suggestion.parameterNames.length));
+ expect(suggestion.hasNamedParameters, isNotNull);
+ }
+
+ CompletionSuggestion assertNotSuggested(String completion) {
+ CompletionSuggestion suggestion = suggestions.firstWhere(
+ (CompletionSuggestion cs) => cs.completion == completion,
+ orElse: () => null);
+ if (suggestion != null) {
+ failedCompletion('did not expect completion: $completion\n $suggestion');
+ }
+ return null;
+ }
+
+ CompletionSuggestion assertSuggest(String completion,
+ {CompletionSuggestionKind csKind: CompletionSuggestionKind.INVOCATION,
+ int relevance: DART_RELEVANCE_DEFAULT,
+ String importUri,
+ protocol.ElementKind elemKind: null,
+ bool isDeprecated: false,
+ bool isPotential: false,
+ String elemFile,
+ int elemOffset}) {
+ CompletionSuggestion cs =
+ getSuggest(completion: completion, csKind: csKind, elemKind: elemKind);
+ if (cs == null) {
+ failedCompletion('expected $completion $csKind $elemKind', suggestions);
+ }
+ expect(cs.kind, equals(csKind));
+ if (isDeprecated) {
+ expect(cs.relevance, equals(DART_RELEVANCE_LOW));
+ } else {
+ expect(cs.relevance, equals(relevance));
+ }
+ expect(cs.importUri, importUri);
+ expect(cs.selectionOffset, equals(completion.length));
+ expect(cs.selectionLength, equals(0));
+ expect(cs.isDeprecated, equals(isDeprecated));
+ expect(cs.isPotential, equals(isPotential));
+ if (cs.element != null) {
+ expect(cs.element.location, isNotNull);
+ expect(cs.element.location.file, isNotNull);
+ expect(cs.element.location.offset, isNotNull);
+ expect(cs.element.location.length, isNotNull);
+ expect(cs.element.location.startColumn, isNotNull);
+ expect(cs.element.location.startLine, isNotNull);
+ }
+ if (elemFile != null) {
+ expect(cs.element.location.file, elemFile);
+ }
+ if (elemOffset != null) {
+ expect(cs.element.location.offset, elemOffset);
+ }
+ return cs;
+ }
+
+ Future computeSuggestions([int times = 200]) async {
+ // Build a request with a target based on a parsed unit
+ CompilationUnit unit = context.parseCompilationUnit(testSource);
+// AnalysisServer server = new AnalysisServerMock(
+// searchEngine: searchEngine, resourceProvider: provider);
+ request = new DartCompletionRequestImpl(
+ new CompletionRequestImpl(
+ context, provider, testSource, completionOffset),
+ new CompletionTarget.forOffset(unit, completionOffset));
+
+ // Compute suggestions
+ DartSuggestionCollectorImpl collector = new DartSuggestionCollectorImpl();
+ var future = contributor.computeSuggestions(request, collector);
+ if (future != null) {
+ Completer<CompilationUnit> completer = new Completer<CompilationUnit>();
+ future.then((_) => completer.complete());
+ await performAnalysis(times, completer);
+ expect(completer.isCompleted, isTrue,
+ reason: 'Expected suggestions in $times iterations');
+ }
+ suggestions = collector.suggestions;
+ }
+
+ DartCompletionContributor createContributor();
+
+ void failedCompletion(String message,
+ [Iterable<CompletionSuggestion> completions]) {
+ StringBuffer sb = new StringBuffer(message);
+ if (completions != null) {
+ sb.write('\n found');
+ completions.toList()
+ ..sort(suggestionComparator)
+ ..forEach((CompletionSuggestion suggestion) {
+ sb.write('\n ${suggestion.completion} -> $suggestion');
+ });
+ }
+ if (request.parsedTarget.containingNode != null) {
+ sb.write('\n in');
+ AstNode node = request.parsedTarget.containingNode;
+ while (node != null) {
+ sb.write('\n ${node.runtimeType}');
+ node = node.parent;
+ }
+ }
+ fail(sb.toString());
+ }
+
+ CompletionSuggestion getSuggest(
+ {String completion: null,
+ CompletionSuggestionKind csKind: null,
+ protocol.ElementKind elemKind: null}) {
+ CompletionSuggestion cs;
+ if (suggestions != null) {
+ suggestions.forEach((CompletionSuggestion s) {
+ if (completion != null && completion != s.completion) {
+ return;
+ }
+ if (csKind != null && csKind != s.kind) {
+ return;
+ }
+ if (elemKind != null) {
+ protocol.Element element = s.element;
+ if (element == null || elemKind != element.kind) {
+ return;
+ }
+ }
+ if (cs == null) {
+ cs = s;
+ } else {
+ failedCompletion('expected exactly one $cs',
+ suggestions.where((s) => s.completion == completion));
+ }
+ });
+ }
+ return cs;
+ }
+
+ Future performAnalysis(int times, Completer completer) {
+ if (completer.isCompleted) return completer.future;
+ if (times == 0) return new Future.value(null);
+ context.performAnalysisTask();
+ // 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, () => performAnalysis(times - 1, completer));
+ }
+
+ @override
+ void setUp() {
+ AnalysisEngine.instance.useTaskModel = true;
+ super.setUp();
+ index = createLocalMemoryIndex();
+ searchEngine = new SearchEngineImpl(index);
+ contributor = createContributor();
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698