private static INavigateToSearchResult ConvertResult( bool containsDots, DeclaredSymbolInfo declaredSymbolInfo, Document document, PatternMatches matches) { var matchKind = GetNavigateToMatchKind(containsDots, matches); // A match is considered to be case sensitive if all its constituent pattern matches are // case sensitive. var isCaseSensitive = matches.All(m => m.IsCaseSensitive); var kind = GetItemKind(declaredSymbolInfo); var navigableItem = NavigableItemFactory.GetItemFromDeclaredSymbolInfo(declaredSymbolInfo, document); return new SearchResult(document, declaredSymbolInfo, kind, matchKind, isCaseSensitive, navigableItem); }
private static NavigateToMatchKind GetNavigateToMatchKind( bool containsDots, PatternMatches matchResult) { // NOTE(cyrusn): Unfortunately, the editor owns how sorting of NavigateToItems works, // and they only provide four buckets for sorting items before they sort by the name // of the items. Because of this, we only have coarse granularity for bucketing things. // // So the question becomes: what do we do if we have multiple match results, and we // need to map to a single MatchKind. // // First, consider a main reason we have multiple match results. And this happened // when the user types a dotted name (like "Microsoft.CodeAnalysis.ISymbol"). Such // a name would match actual entities: Microsoft.CodeAnalysis.ISymbol *and* // Microsoft.CodeAnalysis.IAliasSymbol. The first will be an [Exact, Exact, Exact] // match, and the second will be an [Exact, Exact, CamelCase] match. In this // case our belief is that the names will go from least specific to most specific. // So, the left items may match lots of stuff, while the rightmost items will match // a smaller set of items. As such, we use the last pattern match to try to decide // what type of editor MatchKind to map to. if (containsDots) { var lastResult = matchResult.CandidateMatches.LastOrNullable(); if (lastResult.HasValue) { switch (lastResult.Value.Kind) { case PatternMatchKind.Exact: return NavigateToMatchKind.Exact; case PatternMatchKind.Prefix: return NavigateToMatchKind.Prefix; case PatternMatchKind.Substring: return NavigateToMatchKind.Substring; } } } else { // If it wasn't a dotted name, and we have multiple results, that's because they // had a something like a space separated pattern. In that case, there's no // clear indication as to what is the most important part of the pattern. So // we make the result as good as any constituent part. if (matchResult.Any(r => r.Kind == PatternMatchKind.Exact)) { return NavigateToMatchKind.Exact; } if (matchResult.Any(r => r.Kind == PatternMatchKind.Prefix)) { return NavigateToMatchKind.Prefix; } if (matchResult.Any(r => r.Kind == PatternMatchKind.Substring)) { return NavigateToMatchKind.Substring; } } return NavigateToMatchKind.Regular; }