| // 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/src/test_utilities/test_code_format.dart'; | |
| import 'package:analyzer_plugin/protocol/protocol_common.dart'; | |
| import 'package:test/test.dart'; | |
| import 'analysis_server_base.dart'; | |
| class AbstractCompletionDomainTest extends PubPackageAnalysisServerTest { | |
| // TODO(brianwilkerson): Merge this class and `CompletionTestCase`. | |
| late int completionOffset; // TODO(scheglov): remove it | |
| int? replacementOffset; | |
| late int replacementLength; | |
| List<CompletionSuggestion> suggestions = []; | |
| 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, | |
| int maxResults = 1 << 10, | |
| }) async { | |
| var code = TestCode.parseNormalized(content); | |
| var completionOffset = code.position.offset; | |
| newFile(path, code.code); | |
| return await getSuggestions( | |
| path: path, | |
| completionOffset: completionOffset, | |
| maxResults: maxResults, | |
| ); | |
| } | |
| Future<void> getSuggestions({ | |
| required String path, | |
| required int completionOffset, | |
| required int maxResults, | |
| }) async { | |
| var request = CompletionGetSuggestions2Params( | |
| path, | |
| completionOffset, | |
| maxResults, | |
| ).toRequest('0', clientUriConverter: server.uriConverter); | |
| var response = await handleSuccessfulRequest(request); | |
| var result = CompletionGetSuggestions2Result.fromResponse( | |
| response, | |
| clientUriConverter: server.uriConverter, | |
| ); | |
| replacementOffset = result.replacementOffset; | |
| replacementLength = result.replacementLength; | |
| suggestions = result.suggestions; | |
| } | |
| Future<void> getTestCodeSuggestions(String content) { | |
| return getCodeSuggestions(path: testFile.path, content: content); | |
| } | |
| @override | |
| Future<void> processNotification(Notification notification) async { | |
| if (notification.event == serverNotificationError) { | |
| fail('server error: ${notification.toJson()}'); | |
| } | |
| } | |
| @override | |
| Future<void> setUp() async { | |
| super.setUp(); | |
| await setRoots(included: [workspaceRootPath], excluded: []); | |
| } | |
| } |