blob: e4c9b61cb75db1c79143f3a74e420ff19ebc8c4b [file] [log] [blame]
// Copyright (c) 2018, 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 'dart:collection';
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/src/lsp/handlers/handlers.dart';
import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
import 'package:analysis_server/src/lsp/mapping.dart';
import 'package:analysis_server/src/provisional/completion/completion_core.dart';
import 'package:analysis_server/src/services/completion/completion_core.dart';
import 'package:analysis_server/src/services/completion/completion_performance.dart';
import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
import 'package:analyzer/dart/analysis/results.dart';
// If the client does not provide capabilities.completion.completionItemKind.valueSet
// then we must never send a kind that's not in this list.
final defaultSupportedCompletionKinds = new HashSet<CompletionItemKind>.of([
CompletionItemKind.Text,
CompletionItemKind.Method,
CompletionItemKind.Function,
CompletionItemKind.Constructor,
CompletionItemKind.Field,
CompletionItemKind.Variable,
CompletionItemKind.Class,
CompletionItemKind.Interface,
CompletionItemKind.Module,
CompletionItemKind.Property,
CompletionItemKind.Unit,
CompletionItemKind.Value,
CompletionItemKind.Enum,
CompletionItemKind.Keyword,
CompletionItemKind.Snippet,
CompletionItemKind.Color,
CompletionItemKind.File,
CompletionItemKind.Reference,
]);
class CompletionHandler
extends MessageHandler<CompletionParams, List<CompletionItem>> {
final bool suggestFromUnimportedLibraries;
CompletionHandler(
LspAnalysisServer server, this.suggestFromUnimportedLibraries)
: super(server);
Method get handlesMessage => Method.textDocument_completion;
@override
LspJsonHandler<CompletionParams> get jsonHandler =>
CompletionParams.jsonHandler;
Future<ErrorOr<List<CompletionItem>>> handle(CompletionParams params) async {
if (!isDartDocument(params.textDocument)) {
return success(const []);
}
final completionCapabilities =
server?.clientCapabilities?.textDocument?.completion;
final clientSupportedCompletionKinds =
completionCapabilities?.completionItemKind?.valueSet != null
? new HashSet<CompletionItemKind>.of(
completionCapabilities.completionItemKind.valueSet)
: defaultSupportedCompletionKinds;
final includeSuggestionSets = suggestFromUnimportedLibraries &&
server?.clientCapabilities?.workspace?.applyEdit == true;
final pos = params.position;
final path = pathOfDoc(params.textDocument);
final unit = await path.mapResult(requireResolvedUnit);
final offset = await unit.mapResult((unit) => toOffset(unit.lineInfo, pos));
return offset.mapResult((offset) => _getItems(
completionCapabilities,
clientSupportedCompletionKinds,
includeSuggestionSets,
unit.result,
offset,
));
}
Future<ErrorOr<List<CompletionItem>>> _getItems(
TextDocumentClientCapabilitiesCompletion completionCapabilities,
HashSet<CompletionItemKind> clientSupportedCompletionKinds,
bool includeSuggestionSets,
ResolvedUnitResult unit,
int offset,
) async {
final performance = new CompletionPerformance();
performance.path = unit.path;
performance.setContentsAndOffset(unit.content, offset);
server.performanceStats.completion.add(performance);
final completionRequest =
new CompletionRequestImpl(unit, offset, performance);
try {
CompletionContributor contributor = new DartCompletionManager();
final suggestions =
await contributor.computeSuggestions(completionRequest);
final results = suggestions
.map((item) => toCompletionItem(
completionCapabilities,
clientSupportedCompletionKinds,
unit.lineInfo,
item,
completionRequest.replacementOffset,
completionRequest.replacementLength,
))
.toList();
performance.notificationCount = 1;
performance.suggestionCountFirst = results.length;
performance.suggestionCountLast = results.length;
performance.complete();
return success(results);
} on AbortCompletion {
return success([]);
}
}
}