clang-tools  8.0.0
Quality.h
Go to the documentation of this file.
1 //===--- Quality.h - Ranking alternatives for ambiguous queries --*- C++-*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// Some operations such as code completion produce a set of candidates.
11 /// Usually the user can choose between them, but we should put the best options
12 /// at the top (they're easier to select, and more likely to be seen).
13 ///
14 /// This file defines building blocks for ranking candidates.
15 /// It's used by the features directly and also in the implementation of
16 /// indexes, as indexes also need to heuristically limit their results.
17 ///
18 /// The facilities here are:
19 /// - retrieving scoring signals from e.g. indexes, AST, CodeCompletionString
20 /// These are structured in a way that they can be debugged, and are fairly
21 /// consistent regardless of the source.
22 /// - compute scores from scoring signals. These are suitable for sorting.
23 /// - sorting utilities like the TopN container.
24 /// These could be split up further to isolate dependencies if we care.
25 ///
26 //===----------------------------------------------------------------------===//
27 
28 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_QUALITY_H
29 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_QUALITY_H
30 
31 #include "ExpectedTypes.h"
32 #include "FileDistance.h"
33 #include "clang/Sema/CodeCompleteConsumer.h"
34 #include "llvm/ADT/ArrayRef.h"
35 #include "llvm/ADT/StringRef.h"
36 #include <algorithm>
37 #include <functional>
38 #include <vector>
39 
40 namespace llvm {
41 class raw_ostream;
42 }
43 
44 namespace clang {
45 class CodeCompletionResult;
46 
47 namespace clangd {
48 
49 struct Symbol;
50 class URIDistance;
51 
52 // Signals structs are designed to be aggregated from 0 or more sources.
53 // A default instance has neutral signals, and sources are merged into it.
54 // They can be dumped for debugging, and evaluate()d into a score.
55 
56 /// Attributes of a symbol that affect how much we like it.
58  bool Deprecated = false;
59  bool ReservedName = false; // __foo, _Foo are usually implementation details.
60  // FIXME: make these findable once user types _.
61  bool ImplementationDetail = false;
62  unsigned References = 0;
63 
65  Unknown = 0,
75  } Category = Unknown;
76 
77  void merge(const CodeCompletionResult &SemaCCResult);
78  void merge(const Symbol &IndexResult);
79 
80  // Condense these signals down to a single number, higher is better.
81  float evaluate() const;
82 };
83 llvm::raw_ostream &operator<<(llvm::raw_ostream &,
84  const SymbolQualitySignals &);
85 
86 /// Attributes of a symbol-query pair that affect how much we like it.
88  /// 0-1+ fuzzy-match score for unqualified name. Must be explicitly assigned.
89  float NameMatch = 1;
90  bool Forbidden = false; // Unavailable (e.g const) or inaccessible (private).
91  /// Whether fixits needs to be applied for that completion or not.
92  bool NeedsFixIts = false;
93  bool InBaseClass = false; // A member from base class of the accessed class.
94 
95  URIDistance *FileProximityMatch = nullptr;
96  /// These are used to calculate proximity between the index symbol and the
97  /// query.
98  llvm::StringRef SymbolURI;
99  /// FIXME: unify with index proximity score - signals should be
100  /// source-independent.
101  /// Proximity between best declaration and the query. [0-1], 1 is closest.
102  float SemaFileProximityScore = 0;
103 
104  // Scope proximity is only considered (both index and sema) when this is set.
105  ScopeDistance *ScopeProximityMatch = nullptr;
106  llvm::Optional<llvm::StringRef> SymbolScope;
107  // A symbol from sema should be accessible from the current scope.
108  bool SemaSaysInScope = false;
109 
110  // An approximate measure of where we expect the symbol to be used.
116  } Scope = GlobalScope;
117 
118  enum QueryType {
121  } Query = Generic;
122 
123  CodeCompletionContext::Kind Context = CodeCompletionContext::CCC_Other;
124 
125  // Whether symbol is an instance member of a class.
126  bool IsInstanceMember = false;
127 
128  // Whether clang provided a preferred type in the completion context.
129  bool HadContextType = false;
130  // Whether a source completion item or a symbol had a type information.
131  bool HadSymbolType = false;
132  // Whether the item matches the type expected in the completion context.
133  bool TypeMatchesPreferred = false;
134 
135  void merge(const CodeCompletionResult &SemaResult);
136  void merge(const Symbol &IndexResult);
137 
138  // Condense these signals down to a single number, higher is better.
139  float evaluate() const;
140 };
141 llvm::raw_ostream &operator<<(llvm::raw_ostream &,
142  const SymbolRelevanceSignals &);
143 
144 /// Combine symbol quality and relevance into a single score.
145 float evaluateSymbolAndRelevance(float SymbolQuality, float SymbolRelevance);
146 
147 /// TopN<T> is a lossy container that preserves only the "best" N elements.
148 template <typename T, typename Compare = std::greater<T>> class TopN {
149 public:
150  using value_type = T;
151  TopN(size_t N, Compare Greater = Compare())
152  : N(N), Greater(std::move(Greater)) {}
153 
154  // Adds a candidate to the set.
155  // Returns true if a candidate was dropped to get back under N.
156  bool push(value_type &&V) {
157  bool Dropped = false;
158  if (Heap.size() >= N) {
159  Dropped = true;
160  if (N > 0 && Greater(V, Heap.front())) {
161  std::pop_heap(Heap.begin(), Heap.end(), Greater);
162  Heap.back() = std::move(V);
163  std::push_heap(Heap.begin(), Heap.end(), Greater);
164  }
165  } else {
166  Heap.push_back(std::move(V));
167  std::push_heap(Heap.begin(), Heap.end(), Greater);
168  }
169  assert(Heap.size() <= N);
170  assert(std::is_heap(Heap.begin(), Heap.end(), Greater));
171  return Dropped;
172  }
173 
174  // Returns candidates from best to worst.
175  std::vector<value_type> items() && {
176  std::sort_heap(Heap.begin(), Heap.end(), Greater);
177  assert(Heap.size() <= N);
178  return std::move(Heap);
179  }
180 
181 private:
182  const size_t N;
183  std::vector<value_type> Heap; // Min-heap, comparator is Greater.
184  Compare Greater;
185 };
186 
187 /// Returns a string that sorts in the same order as (-Score, Tiebreak), for
188 /// LSP. (The highest score compares smallest so it sorts at the top).
189 std::string sortText(float Score, llvm::StringRef Tiebreak = "");
190 
192  uint32_t NumberOfParameters = 0;
193  uint32_t NumberOfOptionalParameters = 0;
194  bool ContainsActiveParameter = false;
195  CodeCompleteConsumer::OverloadCandidate::CandidateKind Kind =
196  CodeCompleteConsumer::OverloadCandidate::CandidateKind::CK_Function;
197 };
198 llvm::raw_ostream &operator<<(llvm::raw_ostream &,
199  const SignatureQualitySignals &);
200 
201 } // namespace clangd
202 } // namespace clang
203 
204 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_QUALITY_H
Some operations such as code completion produce a set of candidates.
llvm::Optional< llvm::StringRef > SymbolScope
Definition: Quality.h:106
TopN(size_t N, Compare Greater=Compare())
Definition: Quality.h:151
std::string sortText(float Score, llvm::StringRef Name)
Returns a string that sorts in the same order as (-Score, Tiebreak), for LSP.
Definition: Quality.cpp:452
Attributes of a symbol that affect how much we like it.
Definition: Quality.h:57
BindArgumentKind Kind
bool push(value_type &&V)
Definition: Quality.h:156
const Symbol * IndexResult
A context is an immutable container for per-request data that must be propagated through layers that ...
Definition: Context.h:70
llvm::StringRef SymbolURI
These are used to calculate proximity between the index symbol and the query.
Definition: Quality.h:98
float evaluateSymbolAndRelevance(float SymbolQuality, float SymbolRelevance)
Combine symbol quality and relevance into a single score.
Definition: Quality.cpp:434
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Support lookups like FileDistance, but the lookup keys are symbol scopes.
Definition: FileDistance.h:117
const CodeCompletionResult * SemaResult
std::vector< value_type > items() &&
Definition: Quality.h:175
llvm::raw_ostream & operator<<(llvm::raw_ostream &OS, const CodeCompletion &C)
Attributes of a symbol-query pair that affect how much we like it.
Definition: Quality.h:87
TopN<T> is a lossy container that preserves only the "best" N elements.
Definition: Quality.h:148