blob: 59a5f614f67f3d9bd7b9bb7d2bcbbe44daf5f6b3 [file] [log] [blame]
// Copyright (c) 2021, 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 'package:analysis_server/src/protocol_server.dart';
import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
import 'package:analysis_server/src/services/completion/filtering/fuzzy_matcher.dart';
/// Filters and scores [suggestions] according to how well they match the
/// [pattern]. Sorts [suggestions] by the score, relevance, and name.
List<CompletionSuggestionBuilder> fuzzyFilterSort({
required String pattern,
required List<CompletionSuggestionBuilder> suggestions,
}) {
var matcher = FuzzyMatcher(pattern, matchStyle: MatchStyle.SYMBOL);
double score(CompletionSuggestionBuilder suggestion) {
var suggestionTextToMatch = suggestion.completion;
if (suggestion.kind == CompletionSuggestionKind.NAMED_ARGUMENT) {
var index = suggestionTextToMatch.indexOf(':');
if (index != -1) {
suggestionTextToMatch = suggestionTextToMatch.substring(0, index);
}
}
return matcher.score(suggestionTextToMatch);
}
var scored = suggestions
.map((e) => _FuzzyScoredSuggestion(e, score(e)))
.where((e) => e.score > 0)
.toList();
scored.sort((a, b) {
// Prefer what the user requested by typing.
if (a.score > b.score) {
return -1;
} else if (a.score < b.score) {
return 1;
}
// Then prefer what is more relevant in the context.
if (a.suggestion.relevance != b.suggestion.relevance) {
return b.suggestion.relevance - a.suggestion.relevance;
}
// Other things being equal, sort by name.
return a.suggestion.completion.compareTo(b.suggestion.completion);
});
return scored.map((e) => e.suggestion).toList();
}
/// [CompletionSuggestion] scored using [FuzzyMatcher].
class _FuzzyScoredSuggestion {
final CompletionSuggestionBuilder suggestion;
final double score;
_FuzzyScoredSuggestion(this.suggestion, this.score);
}