13 #include "clang/AST/ASTContext.h" 14 #include "clang/AST/Decl.h" 15 #include "clang/AST/DeclCXX.h" 16 #include "clang/AST/DeclTemplate.h" 17 #include "clang/AST/DeclVisitor.h" 18 #include "clang/Basic/CharInfo.h" 19 #include "clang/Basic/SourceManager.h" 20 #include "clang/Sema/CodeCompleteConsumer.h" 21 #include "llvm/Support/Casting.h" 22 #include "llvm/Support/FormatVariadic.h" 23 #include "llvm/Support/MathExtras.h" 24 #include "llvm/Support/raw_ostream.h" 32 return Name.size() >= 2 && Name[0] ==
'_' &&
33 (isUppercase(Name[1]) || Name[1] ==
'_');
37 auto &SourceMgr = D.getASTContext().getSourceManager();
38 for (
auto *Redecl : D.redecls()) {
39 auto Loc = SourceMgr.getSpellingLoc(Redecl->getLocation());
40 if (SourceMgr.isWrittenInMainFile(
Loc))
47 const auto &
Context = R.Declaration->getASTContext();
48 const auto &SourceMgr =
Context.getSourceManager();
50 const auto Loc = SourceMgr.getExpansionLoc(R.ShadowDecl->getLocation());
51 if (SourceMgr.isWrittenInMainFile(
Loc))
59 :
public ConstDeclVisitor<Switch, SymbolQualitySignals::SymbolCategory> {
61 #define MAP(DeclType, Category) \ 62 SymbolQualitySignals::SymbolCategory Visit##DeclType(const DeclType *) { \ 63 return SymbolQualitySignals::Category; \ 68 MAP(TypeAliasTemplateDecl, Type);
69 MAP(ClassTemplateDecl, Type);
78 return Switch().Visit(&ND);
85 if (R.Kind == CodeCompletionResult::RK_Macro)
89 switch (R.CursorKind) {
90 case CXCursor_CXXMethod:
92 case CXCursor_ModuleImportDecl:
94 case CXCursor_MacroDefinition:
96 case CXCursor_TypeRef:
98 case CXCursor_MemberRef:
100 case CXCursor_Constructor:
110 case index::SymbolKind::Namespace:
111 case index::SymbolKind::NamespaceAlias:
113 case index::SymbolKind::Macro:
115 case index::SymbolKind::Enum:
116 case index::SymbolKind::Struct:
117 case index::SymbolKind::Class:
118 case index::SymbolKind::Protocol:
119 case index::SymbolKind::Extension:
120 case index::SymbolKind::Union:
121 case index::SymbolKind::TypeAlias:
123 case index::SymbolKind::Function:
124 case index::SymbolKind::ClassMethod:
125 case index::SymbolKind::InstanceMethod:
126 case index::SymbolKind::StaticMethod:
127 case index::SymbolKind::InstanceProperty:
128 case index::SymbolKind::ClassProperty:
129 case index::SymbolKind::StaticProperty:
130 case index::SymbolKind::Destructor:
131 case index::SymbolKind::ConversionFunction:
133 case index::SymbolKind::Constructor:
135 case index::SymbolKind::Variable:
136 case index::SymbolKind::Field:
137 case index::SymbolKind::EnumConstant:
138 case index::SymbolKind::Parameter:
140 case index::SymbolKind::Using:
141 case index::SymbolKind::Module:
145 llvm_unreachable(
"Unknown index::SymbolKind");
151 if (
const auto *TP = dyn_cast<FunctionTemplateDecl>(ND))
152 ND = TP->TemplateDecl::getTemplatedDecl();
153 if (
const auto *CM = dyn_cast<CXXMethodDecl>(ND))
154 return !CM->isStatic();
155 return isa<FieldDecl>(ND);
160 case index::SymbolKind::InstanceMethod:
161 case index::SymbolKind::InstanceProperty:
162 case index::SymbolKind::Field:
170 if (SemaCCResult.Availability == CXAvailability_Deprecated)
175 if (SemaCCResult.Declaration) {
176 if (
auto *ID = SemaCCResult.Declaration->getIdentifier())
177 ReservedName = ReservedName ||
isReserved(ID->getName());
178 }
else if (SemaCCResult.Kind == CodeCompletionResult::RK_Macro)
179 ReservedName = ReservedName ||
isReserved(SemaCCResult.Macro->getName());
183 References = std::max(IndexResult.
References, References);
193 if (References >= 10) {
202 float S = std::pow(References, -0.06);
203 Score *= 6.0 * (1 - S) / (1 + S) + 0.59;
235 OS << formatv(
"=== Symbol quality: {0}\n", S.
evaluate());
236 OS << formatv(
"\tReferences: {0}\n", S.
References);
237 OS << formatv(
"\tDeprecated: {0}\n", S.
Deprecated);
238 OS << formatv(
"\tReserved name: {0}\n", S.
ReservedName);
239 OS << formatv(
"\tCategory: {0}\n", static_cast<int>(S.
Category));
246 const DeclContext *DC = D->getDeclContext();
247 if (
auto *R = dyn_cast_or_null<RecordDecl>(D))
248 if (R->isInjectedClassName())
249 DC = DC->getParent();
251 if (isa<CXXConstructorDecl>(D))
252 DC = DC->getParent();
253 bool InClass =
false;
254 for (; !DC->isFileContext(); DC = DC->getParent()) {
255 if (DC->isFunctionOrMethod())
257 InClass = InClass || DC->isRecord();
262 if (D->getLinkageInternal() < ExternalLinkage)
276 if (SemaCCResult.Availability == CXAvailability_NotAvailable ||
277 SemaCCResult.Availability == CXAvailability_NotAccessible)
280 if (SemaCCResult.Declaration) {
288 SemaProximityScore = std::max(DeclProximity, SemaProximityScore);
293 if (SemaCCResult.Declaration)
294 Scope = std::min(Scope,
computeScope(SemaCCResult.Declaration));
299 if (!D || SymbolURI.empty())
301 unsigned Distance = D->
distance(SymbolURI);
316 Score *= 1 + 2 * std::max(
proximityScore(SymbolURI, FileProximityMatch).first,
321 if (Query == CodeComplete) {
340 if (!IsInstanceMember &&
341 (
Context == CodeCompletionContext::CCC_DotMemberAccess ||
342 Context == CodeCompletionContext::CCC_ArrowMemberAccess)) {
350 OS << formatv(
"=== Symbol relevance: {0}\n", S.
evaluate());
351 OS << formatv(
"\tName match: {0}\n", S.
NameMatch);
352 OS << formatv(
"\tForbidden: {0}\n", S.
Forbidden);
354 OS << formatv(
"\tContext: {0}\n", getCompletionKindString(S.
Context));
355 OS << formatv(
"\tSymbol URI: {0}\n", S.
SymbolURI);
358 OS << formatv(
"\tIndex proximity: {0} (distance={1})\n", Score.first,
362 OS << formatv(
"\tQuery type: {0}\n", static_cast<int>(S.
Query));
363 OS << formatv(
"\tScope: {0}\n", static_cast<int>(S.
Scope));
368 return SymbolQuality * SymbolRelevance;
374 static_assert(std::numeric_limits<float>::is_iec559,
"");
375 constexpr uint32_t TopBit = ~(~uint32_t{0} >> 1);
378 uint32_t U = FloatToBits(F);
389 llvm::raw_string_ostream OS(S);
SourceLocation Loc
'#' location in the include directive
static SymbolQualitySignals::SymbolCategory categorize(const NamedDecl &ND)
void merge(const CodeCompletionResult &SemaCCResult)
Some operations such as code completion produce a set of candidates.
static uint32_t encodeFloat(float F)
enum clang::clangd::SymbolQualitySignals::SymbolCategory Category
void merge(const CodeCompletionResult &SemaResult)
std::string sortText(float Score, llvm::StringRef Name)
Returns a string that sorts in the same order as (-Score, Tiebreak), for LSP.
CodeCompletionContext::Kind Context
Attributes of a symbol that affect how much we like it.
float SemaProximityScore
Proximity between best declaration and the query.
enum clang::clangd::SymbolRelevanceSignals::AccessibleScope Scope
index::SymbolInfo SymInfo
static bool isReserved(StringRef Name)
URIDistance * FileProximityMatch
enum clang::clangd::SymbolRelevanceSignals::QueryType Query
clang::find_all_symbols::SymbolInfo SymbolInfo
#define MAP(DeclType, Category)
*that are placed right before the argument **code *void f(bool foo)
Checks that argument comments match parameter names.
SymbolLocation CanonicalDeclaration
const Symbol * IndexResult
static std::pair< float, unsigned > proximityScore(llvm::StringRef SymbolURI, URIDistance *D)
A context is an immutable container for per-request data that must be propagated through layers that ...
static bool hasDeclInMainFile(const Decl &D)
unsigned distance(llvm::StringRef URI)
llvm::StringRef SymbolURI
This is used to calculate proximity between the index symbol and the query.
float evaluateSymbolAndRelevance(float SymbolQuality, float SymbolRelevance)
Combine symbol quality and relevance into a single score.
static bool isInstanceMember(const NamedDecl *ND)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
static SymbolRelevanceSignals::AccessibleScope computeScope(const NamedDecl *D)
float NameMatch
0-1+ fuzzy-match score for unqualified name. Must be explicitly assigned.
Attributes of a symbol-query pair that affect how much we like it.
raw_ostream & operator<<(raw_ostream &OS, const CodeCompletion &C)
static bool hasUsingDeclInMainFile(const CodeCompletionResult &R)