44#include "clang/AST/Decl.h"
45#include "clang/AST/DeclBase.h"
46#include "clang/AST/DeclTemplate.h"
47#include "clang/Basic/CharInfo.h"
48#include "clang/Basic/LangOptions.h"
49#include "clang/Basic/SourceLocation.h"
50#include "clang/Basic/TokenKinds.h"
51#include "clang/Format/Format.h"
52#include "clang/Frontend/CompilerInstance.h"
53#include "clang/Frontend/FrontendActions.h"
54#include "clang/Lex/ExternalPreprocessorSource.h"
55#include "clang/Lex/Lexer.h"
56#include "clang/Lex/Preprocessor.h"
57#include "clang/Lex/PreprocessorOptions.h"
58#include "clang/Sema/CodeCompleteConsumer.h"
59#include "clang/Sema/DeclSpec.h"
60#include "clang/Sema/Sema.h"
61#include "llvm/ADT/ArrayRef.h"
62#include "llvm/ADT/SmallVector.h"
63#include "llvm/ADT/StringExtras.h"
64#include "llvm/ADT/StringRef.h"
65#include "llvm/Support/Casting.h"
66#include "llvm/Support/Compiler.h"
67#include "llvm/Support/Debug.h"
68#include "llvm/Support/Error.h"
69#include "llvm/Support/FormatVariadic.h"
70#include "llvm/Support/ScopedPrinter.h"
78#define DEBUG_TYPE "CodeComplete"
83#if CLANGD_DECISION_FOREST
84const CodeCompleteOptions::CodeCompletionRankingModel
85 CodeCompleteOptions::DefaultRankingModel =
86 CodeCompleteOptions::DecisionForest;
88const CodeCompleteOptions::CodeCompletionRankingModel
89 CodeCompleteOptions::DefaultRankingModel = CodeCompleteOptions::Heuristics;
97toCompletionItemKind(index::SymbolKind Kind,
98 const llvm::StringRef *Signature =
nullptr) {
99 using SK = index::SymbolKind;
103 case SK::IncludeDirective:
108 case SK::NamespaceAlias:
135 case SK::ConversionFunction:
139 case SK::NonTypeTemplateParm:
143 case SK::EnumConstant:
145 case SK::InstanceMethod:
146 case SK::ClassMethod:
147 case SK::StaticMethod:
150 case SK::InstanceProperty:
151 case SK::ClassProperty:
152 case SK::StaticProperty:
154 case SK::Constructor:
156 case SK::TemplateTypeParm:
157 case SK::TemplateTemplateParm:
162 llvm_unreachable(
"Unhandled clang::index::SymbolKind.");
167CompletionItemKind toCompletionItemKind(
const CodeCompletionResult &Res,
168 CodeCompletionContext::Kind CtxKind) {
170 return toCompletionItemKind(index::getSymbolInfo(Res.Declaration).Kind);
171 if (CtxKind == CodeCompletionContext::CCC_IncludedFile)
174 case CodeCompletionResult::RK_Declaration:
175 llvm_unreachable(
"RK_Declaration without Decl");
176 case CodeCompletionResult::RK_Keyword:
178 case CodeCompletionResult::RK_Macro:
182 return Res.MacroDefInfo && Res.MacroDefInfo->isFunctionLike()
185 case CodeCompletionResult::RK_Pattern:
188 llvm_unreachable(
"Unhandled CodeCompletionResult::ResultKind.");
192MarkupContent renderDoc(
const markup::Document &Doc, MarkupKind Kind) {
193 MarkupContent Result;
197 Result.value.append(Doc.asPlainText());
202 Result.value.append(Doc.asEscapedMarkdown());
204 Result.value.append(Doc.asMarkdown());
211 if (!Opts.ImportInsertions || !Opts.MainFileSignals)
213 return Opts.MainFileSignals->InsertionDirective;
217struct RawIdentifier {
218 llvm::StringRef Name;
224struct CompletionCandidate {
225 llvm::StringRef Name;
227 const CodeCompletionResult *SemaResult =
nullptr;
228 const Symbol *IndexResult =
nullptr;
229 const RawIdentifier *IdentifierResult =
nullptr;
230 llvm::SmallVector<SymbolInclude, 1> RankedIncludeHeaders;
234 size_t overloadSet(
const CodeCompleteOptions &Opts, llvm::StringRef FileName,
235 IncludeInserter *Inserter,
236 CodeCompletionContext::Kind CCContextKind)
const {
237 if (!Opts.BundleOverloads.value_or(
false))
243 std::string HeaderForHash;
245 if (
auto Header = headerToInsertIfAllowed(Opts, CCContextKind)) {
246 if (
auto HeaderFile =
toHeaderFile(*Header, FileName)) {
248 Inserter->calculateIncludePath(*HeaderFile, FileName))
251 vlog(
"Code completion header path manipulation failed {0}",
252 HeaderFile.takeError());
257 llvm::SmallString<256> Scratch;
259 switch (IndexResult->SymInfo.Kind) {
260 case index::SymbolKind::ClassMethod:
261 case index::SymbolKind::InstanceMethod:
262 case index::SymbolKind::StaticMethod:
264 llvm_unreachable(
"Don't expect members from index in code completion");
268 case index::SymbolKind::Function:
271 return llvm::hash_combine(
272 (IndexResult->Scope + IndexResult->Name).toStringRef(Scratch),
280 const NamedDecl *D = SemaResult->Declaration;
281 if (!D || !D->isFunctionOrFunctionTemplate())
284 llvm::raw_svector_ostream OS(Scratch);
285 D->printQualifiedName(OS);
287 return llvm::hash_combine(Scratch, HeaderForHash);
289 assert(IdentifierResult);
293 bool contextAllowsHeaderInsertion(CodeCompletionContext::Kind Kind)
const {
296 if (Kind == CodeCompletionContext::CCC_ObjCClassForwardDecl)
302 std::optional<llvm::StringRef>
303 headerToInsertIfAllowed(
const CodeCompleteOptions &Opts,
304 CodeCompletionContext::Kind ContextKind)
const {
306 RankedIncludeHeaders.empty() ||
307 !contextAllowsHeaderInsertion(ContextKind))
309 if (SemaResult && SemaResult->Declaration) {
312 auto &SM = SemaResult->Declaration->getASTContext().getSourceManager();
313 for (
const Decl *RD : SemaResult->Declaration->redecls())
314 if (SM.isInMainFile(SM.getExpansionLoc(RD->getBeginLoc())))
318 for (
const auto &Inc : RankedIncludeHeaders)
319 if ((Inc.Directive & Directive) != 0)
324 using Bundle = llvm::SmallVector<CompletionCandidate, 4>;
327 std::pair<CompletionCandidate::Bundle, CodeCompletion::Scores>;
328struct ScoredBundleGreater {
329 bool operator()(
const ScoredBundle &L,
const ScoredBundle &R) {
330 if (L.second.Total != R.second.Total)
331 return L.second.Total > R.second.Total;
332 return L.first.front().Name <
333 R.first.front().Name;
339std::string removeFirstTemplateArg(llvm::StringRef Signature) {
340 auto Rest = Signature.split(
",").second;
343 return (
"<" + Rest.ltrim()).str();
353struct CodeCompletionBuilder {
354 CodeCompletionBuilder(ASTContext *ASTCtx,
const CompletionCandidate &C,
355 CodeCompletionString *SemaCCS,
356 llvm::ArrayRef<std::string> AccessibleScopes,
357 const IncludeInserter &Includes,
358 llvm::StringRef FileName,
359 CodeCompletionContext::Kind ContextKind,
360 const CodeCompleteOptions &Opts,
361 bool IsUsingDeclaration, tok::TokenKind NextTokenKind)
362 : ASTCtx(ASTCtx), ArgumentLists(Opts.ArgumentLists),
363 IsUsingDeclaration(IsUsingDeclaration), NextTokenKind(NextTokenKind) {
364 Completion.Deprecated =
true;
365 add(C, SemaCCS, ContextKind);
369 Completion.Name = std::string(llvm::StringRef(SemaCCS->getTypedText()));
370 Completion.FilterText = SemaCCS->getAllTypedText();
371 if (Completion.Scope.empty()) {
372 if ((C.SemaResult->Kind == CodeCompletionResult::RK_Declaration) ||
373 (C.SemaResult->Kind == CodeCompletionResult::RK_Pattern))
374 if (
const auto *D = C.SemaResult->getDeclaration())
375 if (
const auto *ND = dyn_cast<NamedDecl>(D))
376 Completion.Scope = std::string(
379 Completion.Kind = toCompletionItemKind(*C.SemaResult, ContextKind);
383 Completion.Name.back() ==
'/')
385 for (
const auto &FixIt : C.SemaResult->FixIts) {
387 FixIt, ASTCtx->getSourceManager(), ASTCtx->getLangOpts()));
389 llvm::sort(Completion.FixIts, [](
const TextEdit &
X,
const TextEdit &Y) {
390 return std::tie(X.range.start.line, X.range.start.character) <
391 std::tie(Y.range.start.line, Y.range.start.character);
395 Completion.Origin |= C.IndexResult->Origin;
396 if (Completion.Scope.empty())
397 Completion.Scope = std::string(C.IndexResult->Scope);
399 Completion.Kind = toCompletionItemKind(C.IndexResult->SymInfo.Kind,
400 &C.IndexResult->Signature);
401 if (Completion.Name.empty())
402 Completion.Name = std::string(C.IndexResult->Name);
403 if (Completion.FilterText.empty())
404 Completion.FilterText = Completion.Name;
407 if (Completion.RequiredQualifier.empty() && !C.SemaResult) {
408 llvm::StringRef ShortestQualifier = C.IndexResult->Scope;
409 for (llvm::StringRef Scope : AccessibleScopes) {
410 llvm::StringRef Qualifier = C.IndexResult->Scope;
411 if (Qualifier.consume_front(Scope) &&
412 Qualifier.size() < ShortestQualifier.size())
413 ShortestQualifier = Qualifier;
415 Completion.RequiredQualifier = std::string(ShortestQualifier);
418 if (C.IdentifierResult) {
421 Completion.Name = std::string(C.IdentifierResult->Name);
422 Completion.FilterText = Completion.Name;
426 auto Inserted = [&](llvm::StringRef Header)
427 -> llvm::Expected<std::pair<std::string, bool>> {
428 auto ResolvedDeclaring =
429 URI::resolve(C.IndexResult->CanonicalDeclaration.FileURI, FileName);
430 if (!ResolvedDeclaring)
431 return ResolvedDeclaring.takeError();
433 if (!ResolvedInserted)
434 return ResolvedInserted.takeError();
435 auto Spelled = Includes.calculateIncludePath(*ResolvedInserted, FileName);
437 return error(
"Header not on include path");
438 return std::make_pair(
440 Includes.shouldInsertInclude(*ResolvedDeclaring, *ResolvedInserted));
443 C.headerToInsertIfAllowed(Opts, ContextKind).has_value();
446 for (
const auto &Inc : C.RankedIncludeHeaders) {
447 if ((Inc.Directive & Directive) == 0)
450 if (
auto ToInclude = Inserted(Inc.Header)) {
451 CodeCompletion::IncludeCandidate Include;
452 Include.Header = ToInclude->first;
453 if (ToInclude->second && ShouldInsert)
454 Include.Insertion = Includes.insert(
456 ? tooling::IncludeDirective::Import
457 : tooling::IncludeDirective::Include);
458 Completion.Includes.push_back(std::move(Include));
460 log(
"Failed to generate include insertion edits for adding header "
461 "(FileURI='{0}', IncludeHeader='{1}') into {2}: {3}",
462 C.IndexResult->CanonicalDeclaration.FileURI, Inc.Header, FileName,
463 ToInclude.takeError());
466 std::stable_partition(Completion.Includes.begin(),
467 Completion.Includes.end(),
468 [](
const CodeCompletion::IncludeCandidate &I) {
469 return !I.Insertion.has_value();
473 void add(
const CompletionCandidate &C, CodeCompletionString *SemaCCS,
474 CodeCompletionContext::Kind ContextKind) {
475 assert(
bool(C.SemaResult) ==
bool(SemaCCS));
476 Bundled.emplace_back();
477 BundledEntry &S = Bundled.back();
478 bool IsConcept =
false;
480 getSignature(*SemaCCS, &S.Signature, &S.SnippetSuffix, C.SemaResult->Kind,
481 C.SemaResult->CursorKind,
482 C.SemaResult->FunctionCanBeCall,
483 &Completion.RequiredQualifier);
485 if (C.SemaResult->Kind == CodeCompletionResult::RK_Declaration)
486 if (
const auto *D = C.SemaResult->getDeclaration())
487 if (isa<ConceptDecl>(D))
489 }
else if (C.IndexResult) {
490 S.Signature = std::string(C.IndexResult->Signature);
491 S.SnippetSuffix = std::string(C.IndexResult->CompletionSnippetSuffix);
492 S.ReturnType = std::string(C.IndexResult->ReturnType);
493 if (C.IndexResult->SymInfo.Kind == index::SymbolKind::Concept)
500 if (IsConcept && ContextKind == CodeCompletionContext::CCC_TopLevel) {
501 S.Signature = removeFirstTemplateArg(S.Signature);
504 S.SnippetSuffix = removeFirstTemplateArg(S.SnippetSuffix);
507 if (!Completion.Documentation) {
508 auto SetDoc = [&](llvm::StringRef Doc) {
510 Completion.Documentation.emplace();
515 SetDoc(C.IndexResult->Documentation);
516 }
else if (C.SemaResult) {
517 const auto DocComment =
getDocComment(*ASTCtx, *C.SemaResult,
522 if (Completion.Deprecated) {
524 Completion.Deprecated &=
525 C.SemaResult->Availability == CXAvailability_Deprecated;
527 Completion.Deprecated &=
532 CodeCompletion build() {
533 Completion.ReturnType = summarizeReturnType();
534 Completion.Signature = summarizeSignature();
535 Completion.SnippetSuffix = summarizeSnippet();
536 Completion.BundleSize = Bundled.size();
537 return std::move(Completion);
541 struct BundledEntry {
542 std::string SnippetSuffix;
543 std::string Signature;
544 std::string ReturnType;
548 template <std::
string BundledEntry::*Member>
549 const std::string *onlyValue()
const {
550 auto B = Bundled.begin(), E = Bundled.end();
551 for (
auto *I = B + 1; I != E; ++I)
552 if (I->*Member != B->*Member)
554 return &(B->*Member);
557 template <
bool BundledEntry::*Member>
const bool *onlyValue()
const {
558 auto B = Bundled.begin(), E = Bundled.end();
559 for (
auto *I = B + 1; I != E; ++I)
560 if (I->*Member != B->*Member)
562 return &(B->*Member);
565 std::string summarizeReturnType()
const {
566 if (
auto *RT = onlyValue<&BundledEntry::ReturnType>())
571 std::string summarizeSnippet()
const {
581 if (IsUsingDeclaration)
583 auto *
Snippet = onlyValue<&BundledEntry::SnippetSuffix>();
588 return None ?
"" : (
Open ?
"(" :
"($0)");
601 if (MayHaveArgList) {
605 if (NextTokenKind == tok::less &&
Snippet->front() ==
'<')
608 if (NextTokenKind == tok::l_paren) {
618 else if (
Snippet->at(I) ==
'<')
621 }
while (Balance > 0);
631 if (MayHaveArgList) {
640 bool EmptyArgs = llvm::StringRef(*Snippet).ends_with(
"()");
642 return None ?
"" : (
Open ?
"<" : (EmptyArgs ?
"<$1>()$0" :
"<$1>($0)"));
644 return None ?
"" : (
Open ?
"(" : (EmptyArgs ?
"()" :
"($0)"));
656 if (llvm::StringRef(*Snippet).ends_with(
"<>"))
658 return None ?
"" : (
Open ?
"<" :
"<$0>");
663 std::string summarizeSignature()
const {
664 if (
auto *Signature = onlyValue<&BundledEntry::Signature>())
672 CodeCompletion Completion;
673 llvm::SmallVector<BundledEntry, 1> Bundled;
678 bool IsUsingDeclaration;
679 tok::TokenKind NextTokenKind;
683SymbolID
getSymbolID(
const CodeCompletionResult &R,
const SourceManager &SM) {
685 case CodeCompletionResult::RK_Declaration:
686 case CodeCompletionResult::RK_Pattern: {
692 case CodeCompletionResult::RK_Macro:
694 case CodeCompletionResult::RK_Keyword:
697 llvm_unreachable(
"unknown CodeCompletionResult kind");
702struct SpecifiedScope {
725 std::vector<std::string> AccessibleScopes;
728 std::vector<std::string> QueryScopes;
731 std::optional<std::string> UnresolvedQualifier;
733 std::optional<std::string> EnclosingNamespace;
735 bool AllowAllScopes =
false;
739 std::vector<std::string> scopesForQualification() {
740 std::set<std::string> Results;
741 for (llvm::StringRef AS : AccessibleScopes)
743 (AS + (UnresolvedQualifier ? *UnresolvedQualifier :
"")).str());
744 return {Results.begin(), Results.end()};
749 std::vector<std::string> scopesForIndexQuery() {
751 std::vector<std::string> EnclosingAtFront;
752 if (EnclosingNamespace.has_value())
753 EnclosingAtFront.push_back(*EnclosingNamespace);
754 std::set<std::string> Deduplicated;
755 for (llvm::StringRef S : QueryScopes)
756 if (S != EnclosingNamespace)
757 Deduplicated.insert((S + UnresolvedQualifier.value_or(
"")).str());
759 EnclosingAtFront.reserve(EnclosingAtFront.size() + Deduplicated.size());
760 llvm::copy(Deduplicated, std::back_inserter(EnclosingAtFront));
762 return EnclosingAtFront;
769SpecifiedScope getQueryScopes(CodeCompletionContext &CCContext,
771 const CompletionPrefix &HeuristicPrefix,
772 const CodeCompleteOptions &Opts) {
773 SpecifiedScope Scopes;
774 for (
auto *Context : CCContext.getVisitedContexts()) {
775 if (isa<TranslationUnitDecl>(Context)) {
776 Scopes.QueryScopes.push_back(
"");
777 Scopes.AccessibleScopes.push_back(
"");
778 }
else if (
const auto *ND = dyn_cast<NamespaceDecl>(Context)) {
784 const CXXScopeSpec *SemaSpecifier =
785 CCContext.getCXXScopeSpecifier().value_or(
nullptr);
787 if (!SemaSpecifier) {
790 if (!HeuristicPrefix.Qualifier.empty()) {
791 vlog(
"Sema said no scope specifier, but we saw {0} in the source code",
792 HeuristicPrefix.Qualifier);
793 StringRef SpelledSpecifier = HeuristicPrefix.Qualifier;
794 if (SpelledSpecifier.consume_front(
"::")) {
795 Scopes.AccessibleScopes = {
""};
796 Scopes.QueryScopes = {
""};
798 Scopes.UnresolvedQualifier = std::string(SpelledSpecifier);
806 Scopes.AllowAllScopes = Opts.AllScopes;
810 if (SemaSpecifier && SemaSpecifier->isValid())
814 Scopes.QueryScopes.push_back(
"");
815 llvm::StringRef SpelledSpecifier = Lexer::getSourceText(
816 CharSourceRange::getCharRange(SemaSpecifier->getRange()),
817 CCSema.SourceMgr, clang::LangOptions());
818 if (SpelledSpecifier.consume_front(
"::"))
819 Scopes.QueryScopes = {
""};
820 Scopes.UnresolvedQualifier = std::string(SpelledSpecifier);
822 if (!Scopes.UnresolvedQualifier->empty())
823 *Scopes.UnresolvedQualifier +=
"::";
825 Scopes.AccessibleScopes = Scopes.QueryScopes;
832bool contextAllowsIndex(
enum CodeCompletionContext::Kind K) {
834 case CodeCompletionContext::CCC_TopLevel:
835 case CodeCompletionContext::CCC_ObjCInterface:
836 case CodeCompletionContext::CCC_ObjCImplementation:
837 case CodeCompletionContext::CCC_ObjCIvarList:
838 case CodeCompletionContext::CCC_ClassStructUnion:
839 case CodeCompletionContext::CCC_Statement:
840 case CodeCompletionContext::CCC_Expression:
841 case CodeCompletionContext::CCC_ObjCMessageReceiver:
842 case CodeCompletionContext::CCC_EnumTag:
843 case CodeCompletionContext::CCC_UnionTag:
844 case CodeCompletionContext::CCC_ClassOrStructTag:
845 case CodeCompletionContext::CCC_ObjCProtocolName:
846 case CodeCompletionContext::CCC_Namespace:
847 case CodeCompletionContext::CCC_Type:
848 case CodeCompletionContext::CCC_ParenthesizedExpression:
849 case CodeCompletionContext::CCC_ObjCInterfaceName:
850 case CodeCompletionContext::CCC_Symbol:
851 case CodeCompletionContext::CCC_SymbolOrNewName:
852 case CodeCompletionContext::CCC_ObjCClassForwardDecl:
853 case CodeCompletionContext::CCC_TopLevelOrExpression:
855 case CodeCompletionContext::CCC_OtherWithMacros:
856 case CodeCompletionContext::CCC_DotMemberAccess:
857 case CodeCompletionContext::CCC_ArrowMemberAccess:
858 case CodeCompletionContext::CCC_ObjCCategoryName:
859 case CodeCompletionContext::CCC_ObjCPropertyAccess:
860 case CodeCompletionContext::CCC_MacroName:
861 case CodeCompletionContext::CCC_MacroNameUse:
862 case CodeCompletionContext::CCC_PreprocessorExpression:
863 case CodeCompletionContext::CCC_PreprocessorDirective:
864 case CodeCompletionContext::CCC_SelectorName:
865 case CodeCompletionContext::CCC_TypeQualifiers:
866 case CodeCompletionContext::CCC_ObjCInstanceMessage:
867 case CodeCompletionContext::CCC_ObjCClassMessage:
868 case CodeCompletionContext::CCC_IncludedFile:
869 case CodeCompletionContext::CCC_Attribute:
871 case CodeCompletionContext::CCC_Other:
872 case CodeCompletionContext::CCC_NaturalLanguage:
873 case CodeCompletionContext::CCC_Recovery:
874 case CodeCompletionContext::CCC_NewName:
877 llvm_unreachable(
"unknown code completion context");
880static bool isInjectedClass(
const NamedDecl &D) {
881 if (
auto *R = dyn_cast_or_null<CXXRecordDecl>(&D))
882 if (R->isInjectedClassName())
888static bool isExcludedMember(
const NamedDecl &D) {
891 if (D.getKind() == Decl::CXXDestructor)
894 if (isInjectedClass(D))
897 auto NameKind = D.getDeclName().getNameKind();
898 if (NameKind == DeclarationName::CXXOperatorName ||
899 NameKind == DeclarationName::CXXLiteralOperatorName ||
900 NameKind == DeclarationName::CXXConversionFunctionName)
911struct CompletionRecorder :
public CodeCompleteConsumer {
912 CompletionRecorder(
const CodeCompleteOptions &Opts,
913 llvm::unique_function<
void()> ResultsCallback)
914 : CodeCompleteConsumer(Opts.getClangCompleteOpts()),
915 CCContext(CodeCompletionContext::CCC_Other), Opts(Opts),
916 CCAllocator(std::make_shared<GlobalCodeCompletionAllocator>()),
917 CCTUInfo(CCAllocator), ResultsCallback(std::move(ResultsCallback)) {
918 assert(this->ResultsCallback);
921 std::vector<CodeCompletionResult> Results;
922 CodeCompletionContext CCContext;
923 Sema *CCSema =
nullptr;
926 void ProcessCodeCompleteResults(
class Sema &S, CodeCompletionContext Context,
927 CodeCompletionResult *InResults,
928 unsigned NumResults)
final {
937 CodeCompletionContext::Kind ContextKind = Context.getKind();
938 if (ContextKind == CodeCompletionContext::CCC_Recovery) {
939 log(
"Code complete: Ignoring sema code complete callback with Recovery "
946 if (NumResults == 0 && !contextAllowsIndex(Context.getKind()))
949 log(
"Multiple code complete callbacks (parser backtracked?). "
950 "Dropping results from context {0}, keeping results from {1}.",
951 getCompletionKindString(Context.getKind()),
952 getCompletionKindString(this->CCContext.getKind()));
960 for (
unsigned I = 0; I < NumResults; ++I) {
961 auto &Result = InResults[I];
964 Result.Kind == CodeCompletionResult::RK_Pattern &&
966 ContextKind != CodeCompletionContext::CCC_IncludedFile)
969 if (Result.Hidden && Result.Declaration &&
970 Result.Declaration->isCXXClassMember())
972 if (!Opts.IncludeIneligibleResults &&
973 (Result.Availability == CXAvailability_NotAvailable ||
974 Result.Availability == CXAvailability_NotAccessible))
976 if (Result.Declaration &&
977 !Context.getBaseType().isNull()
978 && isExcludedMember(*Result.Declaration))
982 if (Result.Declaration && !Context.getCXXScopeSpecifier() &&
983 isInjectedClass(*Result.Declaration))
986 Result.StartsNestedNameSpecifier =
false;
987 Results.push_back(Result);
992 CodeCompletionAllocator &getAllocator()
override {
return *CCAllocator; }
993 CodeCompletionTUInfo &getCodeCompletionTUInfo()
override {
return CCTUInfo; }
997 llvm::StringRef getName(
const CodeCompletionResult &Result) {
998 switch (Result.Kind) {
999 case CodeCompletionResult::RK_Declaration:
1000 if (
auto *ID = Result.Declaration->getIdentifier())
1001 return ID->getName();
1003 case CodeCompletionResult::RK_Keyword:
1004 return Result.Keyword;
1005 case CodeCompletionResult::RK_Macro:
1006 return Result.Macro->getName();
1007 case CodeCompletionResult::RK_Pattern:
1010 auto *CCS = codeCompletionString(Result);
1011 const CodeCompletionString::Chunk *OnlyText =
nullptr;
1012 for (
auto &C : *CCS) {
1013 if (C.Kind != CodeCompletionString::CK_TypedText)
1016 return CCAllocator->CopyString(CCS->getAllTypedText());
1019 return OnlyText ? OnlyText->Text : llvm::StringRef();
1024 CodeCompletionString *codeCompletionString(
const CodeCompletionResult &R) {
1026 return const_cast<CodeCompletionResult &
>(R).CreateCodeCompletionString(
1027 *CCSema, CCContext, *CCAllocator, CCTUInfo,
1032 CodeCompleteOptions Opts;
1033 std::shared_ptr<GlobalCodeCompletionAllocator> CCAllocator;
1034 CodeCompletionTUInfo CCTUInfo;
1035 llvm::unique_function<void()> ResultsCallback;
1038struct ScoredSignature {
1042 SignatureInformation Signature;
1043 SignatureQualitySignals Quality;
1051int paramIndexForArg(
const CodeCompleteConsumer::OverloadCandidate &Candidate,
1053 int NumParams = Candidate.getNumParams();
1054 if (
auto *T = Candidate.getFunctionType()) {
1055 if (
auto *Proto = T->getAs<FunctionProtoType>()) {
1056 if (Proto->isVariadic())
1060 return std::min(Arg, std::max(NumParams - 1, 0));
1063class SignatureHelpCollector final :
public CodeCompleteConsumer {
1065 SignatureHelpCollector(
const clang::CodeCompleteOptions &CodeCompleteOpts,
1066 MarkupKind DocumentationFormat,
1067 const SymbolIndex *Index, SignatureHelp &SigHelp)
1068 : CodeCompleteConsumer(CodeCompleteOpts), SigHelp(SigHelp),
1069 Allocator(std::make_shared<clang::GlobalCodeCompletionAllocator>()),
1070 CCTUInfo(Allocator), Index(Index),
1071 DocumentationFormat(DocumentationFormat) {}
1073 void ProcessOverloadCandidates(Sema &S,
unsigned CurrentArg,
1074 OverloadCandidate *Candidates,
1075 unsigned NumCandidates,
1076 SourceLocation OpenParLoc,
1077 bool Braced)
override {
1078 assert(!OpenParLoc.isInvalid());
1079 SourceManager &SrcMgr = S.getSourceManager();
1080 OpenParLoc = SrcMgr.getFileLoc(OpenParLoc);
1081 if (SrcMgr.isInMainFile(OpenParLoc))
1084 elog(
"Location oustide main file in signature help: {0}",
1085 OpenParLoc.printToString(SrcMgr));
1087 std::vector<ScoredSignature> ScoredSignatures;
1088 SigHelp.signatures.reserve(NumCandidates);
1089 ScoredSignatures.reserve(NumCandidates);
1093 SigHelp.activeSignature = 0;
1094 assert(CurrentArg <= (
unsigned)std::numeric_limits<int>::max() &&
1095 "too many arguments");
1097 SigHelp.activeParameter =
static_cast<int>(CurrentArg);
1099 for (
unsigned I = 0; I < NumCandidates; ++I) {
1100 OverloadCandidate Candidate = Candidates[I];
1104 if (
auto *Func = Candidate.getFunction()) {
1105 if (
auto *Pattern = Func->getTemplateInstantiationPattern())
1106 Candidate = OverloadCandidate(Pattern);
1108 if (
static_cast<int>(I) == SigHelp.activeSignature) {
1113 SigHelp.activeParameter =
1114 paramIndexForArg(Candidate, SigHelp.activeParameter);
1117 const auto *CCS = Candidate.CreateSignatureString(
1118 CurrentArg, S, *Allocator, CCTUInfo,
1120 assert(CCS &&
"Expected the CodeCompletionString to be non-null");
1121 ScoredSignatures.push_back(processOverloadCandidate(
1123 Candidate.getFunction()
1130 llvm::DenseMap<SymbolID, std::string> FetchedDocs;
1132 LookupRequest IndexRequest;
1133 for (
const auto &S : ScoredSignatures) {
1136 IndexRequest.IDs.insert(S.IDForDoc);
1138 Index->lookup(IndexRequest, [&](
const Symbol &S) {
1139 if (!S.Documentation.empty())
1140 FetchedDocs[S.ID] = std::string(S.Documentation);
1142 vlog(
"SigHelp: requested docs for {0} symbols from the index, got {1} "
1143 "symbols with non-empty docs in the response",
1144 IndexRequest.IDs.size(), FetchedDocs.size());
1147 llvm::sort(ScoredSignatures, [](
const ScoredSignature &L,
1148 const ScoredSignature &R) {
1155 if (L.Quality.NumberOfParameters != R.Quality.NumberOfParameters)
1156 return L.Quality.NumberOfParameters < R.Quality.NumberOfParameters;
1157 if (L.Quality.NumberOfOptionalParameters !=
1158 R.Quality.NumberOfOptionalParameters)
1159 return L.Quality.NumberOfOptionalParameters <
1160 R.Quality.NumberOfOptionalParameters;
1161 if (L.Quality.Kind != R.Quality.Kind) {
1162 using OC = CodeCompleteConsumer::OverloadCandidate;
1163 auto KindPriority = [&](OC::CandidateKind K) {
1165 case OC::CK_Aggregate:
1167 case OC::CK_Function:
1169 case OC::CK_FunctionType:
1171 case OC::CK_FunctionProtoTypeLoc:
1173 case OC::CK_FunctionTemplate:
1175 case OC::CK_Template:
1178 llvm_unreachable(
"Unknown overload candidate type.");
1180 return KindPriority(L.Quality.Kind) < KindPriority(R.Quality.Kind);
1182 if (L.Signature.label.size() != R.Signature.label.size())
1183 return L.Signature.label.size() < R.Signature.label.size();
1184 return L.Signature.label < R.Signature.label;
1187 for (
auto &SS : ScoredSignatures) {
1189 SS.IDForDoc ? FetchedDocs.find(SS.IDForDoc) : FetchedDocs.end();
1190 if (IndexDocIt != FetchedDocs.end()) {
1191 markup::Document SignatureComment;
1193 SS.Signature.documentation =
1194 renderDoc(SignatureComment, DocumentationFormat);
1197 SigHelp.signatures.push_back(std::move(SS.Signature));
1201 GlobalCodeCompletionAllocator &getAllocator()
override {
return *Allocator; }
1203 CodeCompletionTUInfo &getCodeCompletionTUInfo()
override {
return CCTUInfo; }
1206 void processParameterChunk(llvm::StringRef ChunkText,
1207 SignatureInformation &Signature)
const {
1209 unsigned ParamStartOffset =
lspLength(Signature.label);
1210 unsigned ParamEndOffset = ParamStartOffset +
lspLength(ChunkText);
1214 Signature.label += ChunkText;
1215 ParameterInformation
Info;
1216 Info.labelOffsets.emplace(ParamStartOffset, ParamEndOffset);
1218 Info.labelString = std::string(ChunkText);
1220 Signature.parameters.push_back(std::move(
Info));
1223 void processOptionalChunk(
const CodeCompletionString &CCS,
1224 SignatureInformation &Signature,
1225 SignatureQualitySignals &Signal)
const {
1226 for (
const auto &Chunk : CCS) {
1227 switch (Chunk.Kind) {
1228 case CodeCompletionString::CK_Optional:
1229 assert(Chunk.Optional &&
1230 "Expected the optional code completion string to be non-null.");
1231 processOptionalChunk(*Chunk.Optional, Signature, Signal);
1233 case CodeCompletionString::CK_VerticalSpace:
1235 case CodeCompletionString::CK_CurrentParameter:
1236 case CodeCompletionString::CK_Placeholder:
1237 processParameterChunk(Chunk.Text, Signature);
1238 Signal.NumberOfOptionalParameters++;
1241 Signature.label += Chunk.Text;
1249 ScoredSignature processOverloadCandidate(
const OverloadCandidate &Candidate,
1250 const CodeCompletionString &CCS,
1251 llvm::StringRef DocComment)
const {
1252 SignatureInformation Signature;
1253 SignatureQualitySignals Signal;
1254 const char *ReturnType =
nullptr;
1256 markup::Document OverloadComment;
1258 Signature.documentation = renderDoc(OverloadComment, DocumentationFormat);
1259 Signal.Kind = Candidate.getKind();
1261 for (
const auto &Chunk : CCS) {
1262 switch (Chunk.Kind) {
1263 case CodeCompletionString::CK_ResultType:
1266 assert(!ReturnType &&
"Unexpected CK_ResultType");
1267 ReturnType = Chunk.Text;
1269 case CodeCompletionString::CK_CurrentParameter:
1270 case CodeCompletionString::CK_Placeholder:
1271 processParameterChunk(Chunk.Text, Signature);
1272 Signal.NumberOfParameters++;
1274 case CodeCompletionString::CK_Optional: {
1276 assert(Chunk.Optional &&
1277 "Expected the optional code completion string to be non-null.");
1278 processOptionalChunk(*Chunk.Optional, Signature, Signal);
1281 case CodeCompletionString::CK_VerticalSpace:
1284 Signature.label += Chunk.Text;
1289 Signature.label +=
" -> ";
1290 Signature.label += ReturnType;
1292 dlog(
"Signal for {0}: {1}", Signature, Signal);
1293 ScoredSignature Result;
1294 Result.Signature = std::move(Signature);
1295 Result.Quality = Signal;
1296 const FunctionDecl *Func = Candidate.getFunction();
1297 if (Func && Result.Signature.documentation.value.empty()) {
1305 SignatureHelp &SigHelp;
1306 std::shared_ptr<clang::GlobalCodeCompletionAllocator> Allocator;
1307 CodeCompletionTUInfo CCTUInfo;
1308 const SymbolIndex *Index;
1309 MarkupKind DocumentationFormat;
1314class ParamNameCollector final :
public CodeCompleteConsumer {
1316 ParamNameCollector(
const clang::CodeCompleteOptions &CodeCompleteOpts,
1317 std::set<std::string> &ParamNames)
1318 : CodeCompleteConsumer(CodeCompleteOpts),
1319 Allocator(std::make_shared<clang::GlobalCodeCompletionAllocator>()),
1320 CCTUInfo(Allocator), ParamNames(ParamNames) {}
1322 void ProcessOverloadCandidates(Sema &S,
unsigned CurrentArg,
1323 OverloadCandidate *Candidates,
1324 unsigned NumCandidates,
1325 SourceLocation OpenParLoc,
1326 bool Braced)
override {
1327 assert(CurrentArg <= (
unsigned)std::numeric_limits<int>::max() &&
1328 "too many arguments");
1330 for (
unsigned I = 0; I < NumCandidates; ++I) {
1331 if (
const NamedDecl *ND = Candidates[I].getParamDecl(CurrentArg))
1332 if (
const auto *II = ND->getIdentifier())
1333 ParamNames.emplace(II->getName());
1338 GlobalCodeCompletionAllocator &getAllocator()
override {
return *Allocator; }
1340 CodeCompletionTUInfo &getCodeCompletionTUInfo()
override {
return CCTUInfo; }
1342 std::shared_ptr<clang::GlobalCodeCompletionAllocator> Allocator;
1343 CodeCompletionTUInfo CCTUInfo;
1344 std::set<std::string> &ParamNames;
1347struct SemaCompleteInput {
1351 const std::optional<PreamblePatch> Patch;
1352 const ParseInputs &ParseInput;
1355void loadMainFilePreambleMacros(
const Preprocessor &PP,
1360 ExternalPreprocessorSource *PreambleMacros = PP.getExternalSource();
1363 const auto &ITable = PP.getIdentifierTable();
1364 IdentifierInfoLookup *PreambleIdentifiers =
1365 ITable.getExternalIdentifierLookup();
1367 if (!PreambleIdentifiers || !PreambleMacros)
1369 for (
const auto &MacroName :
Preamble.Macros.Names) {
1370 if (ITable.find(MacroName.getKey()) != ITable.end())
1372 if (
auto *II = PreambleIdentifiers->get(MacroName.getKey()))
1373 if (II->isOutOfDate())
1374 PreambleMacros->updateOutOfDateIdentifier(*II);
1380bool semaCodeComplete(std::unique_ptr<CodeCompleteConsumer> Consumer,
1381 const clang::CodeCompleteOptions &Options,
1382 const SemaCompleteInput &Input,
1383 IncludeStructure *Includes =
nullptr) {
1384 trace::Span Tracer(
"Sema completion");
1386 IgnoreDiagnostics IgnoreDiags;
1389 elog(
"Couldn't create CompilerInvocation");
1392 auto &FrontendOpts = CI->getFrontendOpts();
1393 FrontendOpts.SkipFunctionBodies =
true;
1395 CI->getLangOpts().SpellChecking =
false;
1399 CI->getLangOpts().DelayedTemplateParsing =
false;
1401 FrontendOpts.CodeCompleteOpts = Options;
1402 FrontendOpts.CodeCompletionAt.FileName = std::string(Input.FileName);
1403 std::tie(FrontendOpts.CodeCompletionAt.Line,
1404 FrontendOpts.CodeCompletionAt.Column) =
1407 std::unique_ptr<llvm::MemoryBuffer> ContentsBuffer =
1408 llvm::MemoryBuffer::getMemBuffer(Input.ParseInput.Contents,
1411 CI->getDiagnosticOpts().IgnoreWarnings =
true;
1418 PreambleBounds PreambleRegion =
1419 ComputePreambleBounds(CI->getLangOpts(), *ContentsBuffer, 0);
1420 bool CompletingInPreamble = Input.Offset < PreambleRegion.Size ||
1421 (!PreambleRegion.PreambleEndsAtStartOfLine &&
1422 Input.Offset == PreambleRegion.Size);
1424 Input.Patch->apply(*CI);
1427 llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS =
1428 Input.ParseInput.TFS->view(Input.ParseInput.CompileCommand.Directory);
1429 if (Input.Preamble.StatCache)
1430 VFS = Input.Preamble.StatCache->getConsumingFS(std::move(VFS));
1432 std::move(CI), !CompletingInPreamble ? &Input.Preamble.Preamble :
nullptr,
1433 std::move(ContentsBuffer), std::move(VFS), IgnoreDiags);
1434 Clang->getPreprocessorOpts().SingleFileParseMode = CompletingInPreamble;
1435 Clang->setCodeCompletionConsumer(Consumer.release());
1437 if (Input.Preamble.RequiredModules)
1438 Input.Preamble.RequiredModules->adjustHeaderSearchOptions(
1439 Clang->getHeaderSearchOpts());
1442 if (!Action.BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0])) {
1443 log(
"BeginSourceFile() failed when running codeComplete for {0}",
1453 loadMainFilePreambleMacros(Clang->getPreprocessor(), Input.Preamble);
1455 Includes->collect(*Clang);
1456 if (llvm::Error Err = Action.Execute()) {
1457 log(
"Execute() failed when running codeComplete for {0}: {1}",
1458 Input.FileName,
toString(std::move(Err)));
1461 Action.EndSourceFile();
1467bool allowIndex(CodeCompletionContext &CC) {
1468 if (!contextAllowsIndex(CC.getKind()))
1471 auto Scope = CC.getCXXScopeSpecifier();
1476 switch ((*Scope)->getScopeRep().getKind()) {
1477 case NestedNameSpecifier::Kind::Null:
1478 case NestedNameSpecifier::Kind::Global:
1479 case NestedNameSpecifier::Kind::Namespace:
1481 case NestedNameSpecifier::Kind::MicrosoftSuper:
1482 case NestedNameSpecifier::Kind::Type:
1485 llvm_unreachable(
"invalid NestedNameSpecifier kind");
1490bool includeSymbolFromIndex(CodeCompletionContext::Kind Kind,
1491 const Symbol &Sym) {
1495 if (Sym.SymInfo.Kind == index::SymbolKind::Protocol &&
1496 Sym.SymInfo.Lang == index::SymbolLanguage::ObjC)
1497 return Kind == CodeCompletionContext::CCC_ObjCProtocolName;
1498 else if (Kind == CodeCompletionContext::CCC_ObjCProtocolName)
1502 if (Kind == CodeCompletionContext::CCC_ObjCClassForwardDecl)
1503 return Sym.SymInfo.Kind == index::SymbolKind::Class &&
1504 Sym.SymInfo.Lang == index::SymbolLanguage::ObjC;
1508std::future<std::pair<bool, SymbolSlab>>
1509startAsyncFuzzyFind(
const SymbolIndex &Index,
const FuzzyFindRequest &Req) {
1511 trace::Span Tracer(
"Async fuzzyFind");
1512 SymbolSlab::Builder Syms;
1514 Index.fuzzyFind(Req, [&Syms](
const Symbol &Sym) { Syms.insert(Sym); });
1515 return std::make_pair(Incomplete, std::move(Syms).build());
1522FuzzyFindRequest speculativeFuzzyFindRequestForCompletion(
1523 FuzzyFindRequest CachedReq,
const CompletionPrefix &HeuristicPrefix) {
1524 CachedReq.Query = std::string(HeuristicPrefix.Name);
1532findTokenAfterCompletionPoint(SourceLocation CompletionPoint,
1533 const SourceManager &SM,
1534 const LangOptions &LangOpts) {
1535 SourceLocation Loc = CompletionPoint;
1536 if (Loc.isMacroID()) {
1537 if (!Lexer::isAtEndOfMacroExpansion(Loc, SM, LangOpts, &Loc))
1538 return std::nullopt;
1546 Loc = Loc.getLocWithOffset(1);
1549 std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
1552 bool InvalidTemp =
false;
1553 StringRef
File = SM.getBufferData(LocInfo.first, &InvalidTemp);
1555 return std::nullopt;
1557 const char *TokenBegin =
File.data() + LocInfo.second;
1560 Lexer TheLexer(SM.getLocForStartOfFile(LocInfo.first), LangOpts,
File.begin(),
1561 TokenBegin,
File.end());
1564 TheLexer.LexFromRawLexer(Tok);
1597class CodeCompleteFlow {
1599 IncludeStructure Includes;
1600 SpeculativeFuzzyFind *SpecFuzzyFind;
1601 const CodeCompleteOptions &Opts;
1604 CompletionRecorder *Recorder =
nullptr;
1605 CodeCompletionContext::Kind CCContextKind = CodeCompletionContext::CCC_Other;
1606 bool IsUsingDeclaration =
false;
1610 tok::TokenKind NextTokenKind = tok::eof;
1612 int NSema = 0, NIndex = 0, NSemaAndIndex = 0, NIdent = 0;
1613 bool Incomplete =
false;
1614 CompletionPrefix HeuristicPrefix;
1615 std::optional<FuzzyMatcher> Filter;
1616 Range ReplacedRange;
1617 std::vector<std::string> QueryScopes;
1618 std::vector<std::string> AccessibleScopes;
1620 std::optional<ScopeDistance> ScopeProximity;
1621 std::optional<OpaqueType> PreferredType;
1623 bool AllScopes =
false;
1624 llvm::StringSet<> ContextWords;
1627 std::optional<IncludeInserter> Inserter;
1628 std::optional<URIDistance> FileProximity;
1633 std::optional<FuzzyFindRequest> SpecReq;
1637 CodeCompleteFlow(
PathRef FileName,
const IncludeStructure &Includes,
1638 SpeculativeFuzzyFind *SpecFuzzyFind,
1639 const CodeCompleteOptions &Opts)
1640 : FileName(FileName), Includes(Includes), SpecFuzzyFind(SpecFuzzyFind),
1643 CodeCompleteResult
run(
const SemaCompleteInput &SemaCCInput) && {
1644 trace::Span Tracer(
"CodeCompleteFlow");
1646 SemaCCInput.Offset);
1647 populateContextWords(SemaCCInput.ParseInput.Contents);
1648 if (Opts.Index && SpecFuzzyFind && SpecFuzzyFind->CachedReq) {
1649 assert(!SpecFuzzyFind->Result.valid());
1650 SpecReq = speculativeFuzzyFindRequestForCompletion(
1651 *SpecFuzzyFind->CachedReq, HeuristicPrefix);
1652 SpecFuzzyFind->Result = startAsyncFuzzyFind(*Opts.Index, *SpecReq);
1658 CodeCompleteResult Output;
1659 auto RecorderOwner = std::make_unique<CompletionRecorder>(Opts, [&]() {
1660 assert(Recorder &&
"Recorder is not set");
1661 CCContextKind = Recorder->CCContext.getKind();
1662 IsUsingDeclaration = Recorder->CCContext.isUsingDeclaration();
1664 SemaCCInput.ParseInput.Contents,
1665 *SemaCCInput.ParseInput.TFS,
false);
1666 const auto NextToken = findTokenAfterCompletionPoint(
1667 Recorder->CCSema->getPreprocessor().getCodeCompletionLoc(),
1668 Recorder->CCSema->getSourceManager(), Recorder->CCSema->LangOpts);
1670 NextTokenKind = NextToken->getKind();
1674 SemaCCInput.FileName, SemaCCInput.ParseInput.Contents, Style,
1675 SemaCCInput.ParseInput.CompileCommand.Directory,
1676 &Recorder->CCSema->getPreprocessor().getHeaderSearchInfo(),
1679 for (
const auto &Inc : Includes.MainFileIncludes)
1680 Inserter->addExisting(Inc);
1686 FileDistanceOptions ProxOpts{};
1687 const auto &SM = Recorder->CCSema->getSourceManager();
1688 llvm::StringMap<SourceParams> ProxSources;
1690 Includes.getID(SM.getFileEntryForID(SM.getMainFileID()));
1692 for (
auto &HeaderIDAndDepth : Includes.includeDepth(*MainFileID)) {
1694 ProxSources[Includes.getRealPath(HeaderIDAndDepth.getFirst())];
1695 Source.Cost = HeaderIDAndDepth.getSecond() * ProxOpts.IncludeCost;
1699 if (HeaderIDAndDepth.getSecond() > 0)
1700 Source.MaxUpTraversals = 1;
1702 FileProximity.emplace(ProxSources, ProxOpts);
1704 Output = runWithSema();
1707 getCompletionKindString(CCContextKind));
1708 log(
"Code complete: sema context {0}, query scopes [{1}] (AnyScope={2}), "
1709 "expected type {3}{4}",
1710 getCompletionKindString(CCContextKind),
1711 llvm::join(QueryScopes.begin(), QueryScopes.end(),
","), AllScopes,
1712 PreferredType ? Recorder->CCContext.getPreferredType().getAsString()
1714 IsUsingDeclaration ?
", inside using declaration" :
"");
1717 Recorder = RecorderOwner.get();
1719 semaCodeComplete(std::move(RecorderOwner), Opts.getClangCompleteOpts(),
1720 SemaCCInput, &Includes);
1721 logResults(Output, Tracer);
1725 void logResults(
const CodeCompleteResult &Output,
const trace::Span &Tracer) {
1728 SPAN_ATTACH(Tracer,
"merged_results", NSemaAndIndex);
1729 SPAN_ATTACH(Tracer,
"identifier_results", NIdent);
1730 SPAN_ATTACH(Tracer,
"returned_results", int64_t(Output.Completions.size()));
1731 SPAN_ATTACH(Tracer,
"incomplete", Output.HasMore);
1732 log(
"Code complete: {0} results from Sema, {1} from Index, "
1733 "{2} matched, {3} from identifiers, {4} returned{5}.",
1734 NSema, NIndex, NSemaAndIndex, NIdent, Output.Completions.size(),
1735 Output.HasMore ?
" (incomplete)" :
"");
1736 assert(!Opts.Limit || Output.Completions.size() <= Opts.Limit);
1741 CodeCompleteResult runWithoutSema(llvm::StringRef Content,
size_t Offset,
1742 const ThreadsafeFS &TFS) && {
1743 trace::Span Tracer(
"CodeCompleteWithoutSema");
1746 populateContextWords(Content);
1747 CCContextKind = CodeCompletionContext::CCC_Recovery;
1748 IsUsingDeclaration =
false;
1749 Filter = FuzzyMatcher(HeuristicPrefix.Name);
1751 ReplacedRange.start = ReplacedRange.end = Pos;
1752 ReplacedRange.start.character -= HeuristicPrefix.Name.size();
1754 llvm::StringMap<SourceParams> ProxSources;
1755 ProxSources[FileName].Cost = 0;
1756 FileProximity.emplace(ProxSources);
1760 Inserter.emplace(FileName, Content, Style,
1766 std::vector<RawIdentifier> IdentifierResults;
1767 for (
const auto &IDAndCount : Identifiers) {
1769 ID.Name = IDAndCount.first();
1770 ID.References = IDAndCount.second;
1772 if (ID.Name == HeuristicPrefix.Name)
1774 if (ID.References > 0)
1775 IdentifierResults.push_back(std::move(ID));
1781 SpecifiedScope Scopes;
1783 Content.take_front(Offset), format::getFormattingLangOpts(Style));
1784 for (std::string &S : Scopes.QueryScopes)
1787 if (HeuristicPrefix.Qualifier.empty())
1788 AllScopes = Opts.AllScopes;
1789 else if (HeuristicPrefix.Qualifier.starts_with(
"::")) {
1790 Scopes.QueryScopes = {
""};
1791 Scopes.UnresolvedQualifier =
1792 std::string(HeuristicPrefix.Qualifier.drop_front(2));
1794 Scopes.UnresolvedQualifier = std::string(HeuristicPrefix.Qualifier);
1796 QueryScopes = Scopes.scopesForIndexQuery();
1797 AccessibleScopes = QueryScopes;
1798 ScopeProximity.emplace(QueryScopes);
1800 SymbolSlab IndexResults = Opts.Index ? queryIndex() : SymbolSlab();
1802 CodeCompleteResult Output = toCodeCompleteResult(mergeResults(
1803 {}, IndexResults, IdentifierResults));
1804 Output.RanParser =
false;
1805 logResults(Output, Tracer);
1810 void populateContextWords(llvm::StringRef Content) {
1812 unsigned RangeEnd = HeuristicPrefix.Qualifier.begin() - Content.data(),
1813 RangeBegin = RangeEnd;
1814 for (
size_t I = 0; I < 3 && RangeBegin > 0; ++I) {
1815 auto PrevNL = Content.rfind(
'\n', RangeBegin);
1816 if (PrevNL == StringRef::npos) {
1820 RangeBegin = PrevNL;
1823 ContextWords =
collectWords(Content.slice(RangeBegin, RangeEnd));
1824 dlog(
"Completion context words: {0}",
1825 llvm::join(ContextWords.keys(),
", "));
1830 CodeCompleteResult runWithSema() {
1831 const auto &CodeCompletionRange = CharSourceRange::getCharRange(
1832 Recorder->CCSema->getPreprocessor().getCodeCompletionTokenRange());
1838 if (CodeCompletionRange.isValid()) {
1840 CodeCompletionRange);
1843 Recorder->CCSema->getSourceManager(),
1844 Recorder->CCSema->getPreprocessor().getCodeCompletionLoc());
1845 ReplacedRange.start = ReplacedRange.end = Pos;
1847 Filter = FuzzyMatcher(
1848 Recorder->CCSema->getPreprocessor().getCodeCompletionFilter());
1849 auto SpecifiedScopes = getQueryScopes(
1850 Recorder->CCContext, *Recorder->CCSema, HeuristicPrefix, Opts);
1852 QueryScopes = SpecifiedScopes.scopesForIndexQuery();
1853 AccessibleScopes = SpecifiedScopes.scopesForQualification();
1854 AllScopes = SpecifiedScopes.AllowAllScopes;
1855 if (!QueryScopes.empty())
1856 ScopeProximity.emplace(QueryScopes);
1859 Recorder->CCContext.getPreferredType());
1865 auto IndexResults = (Opts.Index && allowIndex(Recorder->CCContext))
1868 trace::Span Tracer(
"Populate CodeCompleteResult");
1871 mergeResults(Recorder->Results, IndexResults, {});
1872 return toCodeCompleteResult(Top);
1876 toCodeCompleteResult(
const std::vector<ScoredBundle> &Scored) {
1877 CodeCompleteResult Output;
1882 llvm::DenseMap<SymbolID, uint32_t> SymbolToCompletion;
1883 for (
auto &C : Scored) {
1884 Output.Completions.push_back(toCodeCompletion(C.first));
1885 Output.Completions.back().Score = C.second;
1886 Output.Completions.back().CompletionTokenRange = ReplacedRange;
1887 if (Opts.Index && !Output.Completions.back().Documentation) {
1888 for (
auto &Cand : C.first) {
1889 if (Cand.SemaResult &&
1890 Cand.SemaResult->Kind == CodeCompletionResult::RK_Declaration) {
1891 const NamedDecl *DeclToLookup = Cand.SemaResult->getDeclaration();
1895 if (
const NamedDecl *Adjusted =
1896 dyn_cast<NamedDecl>(&adjustDeclToTemplate(*DeclToLookup))) {
1897 DeclToLookup = Adjusted;
1903 SymbolToCompletion[ID] = Output.Completions.size() - 1;
1908 Output.HasMore = Incomplete;
1909 Output.Context = CCContextKind;
1910 Output.CompletionRange = ReplacedRange;
1914 Opts.Index->lookup(Req, [&](
const Symbol &S) {
1915 if (S.Documentation.empty())
1917 auto &C = Output.Completions[SymbolToCompletion.at(S.ID)];
1918 C.Documentation.emplace();
1926 SymbolSlab queryIndex() {
1927 trace::Span Tracer(
"Query index");
1928 SPAN_ATTACH(Tracer,
"limit", int64_t(Opts.Limit));
1931 FuzzyFindRequest Req;
1933 Req.Limit = Opts.Limit;
1934 Req.Query = std::string(Filter->pattern());
1935 Req.RestrictForCodeCompletion =
true;
1936 Req.Scopes = QueryScopes;
1937 Req.AnyScope = AllScopes;
1939 Req.ProximityPaths.push_back(std::string(FileName));
1941 Req.PreferredTypes.push_back(std::string(PreferredType->raw()));
1942 vlog(
"Code complete: fuzzyFind({0:2})",
toJSON(Req));
1945 SpecFuzzyFind->NewReq = Req;
1946 if (SpecFuzzyFind && SpecFuzzyFind->Result.valid() && (*SpecReq == Req)) {
1947 vlog(
"Code complete: speculative fuzzy request matches the actual index "
1948 "request. Waiting for the speculative index results.");
1951 trace::Span WaitSpec(
"Wait speculative results");
1952 auto SpecRes = SpecFuzzyFind->Result.get();
1953 Incomplete |= SpecRes.first;
1954 return std::move(SpecRes.second);
1957 SPAN_ATTACH(Tracer,
"Speculative results",
false);
1960 SymbolSlab::Builder ResultsBuilder;
1961 Incomplete |= Opts.Index->fuzzyFind(
1962 Req, [&](
const Symbol &Sym) { ResultsBuilder.insert(Sym); });
1963 return std::move(ResultsBuilder).build();
1971 std::vector<ScoredBundle>
1972 mergeResults(
const std::vector<CodeCompletionResult> &SemaResults,
1973 const SymbolSlab &IndexResults,
1974 const std::vector<RawIdentifier> &IdentifierResults) {
1975 trace::Span Tracer(
"Merge and score results");
1976 std::vector<CompletionCandidate::Bundle> Bundles;
1977 llvm::DenseMap<size_t, size_t> BundleLookup;
1978 auto AddToBundles = [&](
const CodeCompletionResult *SemaResult,
1979 const Symbol *IndexResult,
1980 const RawIdentifier *IdentifierResult) {
1981 CompletionCandidate C;
1982 C.SemaResult = SemaResult;
1983 C.IndexResult = IndexResult;
1984 C.IdentifierResult = IdentifierResult;
1985 if (C.IndexResult) {
1986 C.Name = IndexResult->Name;
1988 }
else if (C.SemaResult) {
1989 C.Name = Recorder->getName(*SemaResult);
1991 assert(IdentifierResult);
1992 C.Name = IdentifierResult->Name;
1994 if (
auto OverloadSet = C.overloadSet(
1995 Opts, FileName, Inserter ? &*Inserter :
nullptr, CCContextKind)) {
1996 auto Ret = BundleLookup.try_emplace(OverloadSet, Bundles.size());
1998 Bundles.emplace_back();
1999 Bundles[Ret.first->second].push_back(std::move(C));
2001 Bundles.emplace_back();
2002 Bundles.back().push_back(std::move(C));
2005 llvm::DenseSet<const Symbol *> UsedIndexResults;
2006 auto CorrespondingIndexResult =
2007 [&](
const CodeCompletionResult &SemaResult) ->
const Symbol * {
2009 getSymbolID(SemaResult, Recorder->CCSema->getSourceManager())) {
2010 auto I = IndexResults.find(SymID);
2011 if (I != IndexResults.end()) {
2012 UsedIndexResults.insert(&*I);
2019 for (
auto &SemaResult : SemaResults)
2020 AddToBundles(&SemaResult, CorrespondingIndexResult(SemaResult),
nullptr);
2022 for (
const auto &IndexResult : IndexResults) {
2023 if (UsedIndexResults.count(&IndexResult))
2025 if (!includeSymbolFromIndex(CCContextKind, IndexResult))
2027 AddToBundles(
nullptr, &IndexResult,
nullptr);
2030 for (
const auto &Ident : IdentifierResults)
2031 AddToBundles(
nullptr,
nullptr, &Ident);
2033 TopN<ScoredBundle, ScoredBundleGreater> Top(
2034 Opts.Limit == 0 ? std::numeric_limits<size_t>::max() : Opts.Limit);
2035 for (
auto &Bundle : Bundles)
2036 addCandidate(Top, std::move(Bundle));
2037 return std::move(Top).items();
2040 std::optional<float> fuzzyScore(
const CompletionCandidate &C) {
2043 const auto IsMacroResult =
2045 C.SemaResult->Kind == CodeCompletionResult::RK_Macro) ||
2047 C.IndexResult->SymInfo.Kind == index::SymbolKind::Macro));
2050 return Filter->match(C.Name);
2053 bool RequireExactPrefix =
2054 Opts.MacroFilter == MacroFilterPolicy::ExactPrefix ||
2055 C.Name.starts_with_insensitive(
"_") ||
2056 C.Name.ends_with_insensitive(
"_");
2058 if (RequireExactPrefix &&
2059 !C.Name.starts_with_insensitive(Filter->pattern())) {
2060 return std::nullopt;
2063 return Filter->match(C.Name);
2066 CodeCompletion::Scores
2067 evaluateCompletion(
const SymbolQualitySignals &Quality,
2068 const SymbolRelevanceSignals &Relevance) {
2069 using RM = CodeCompleteOptions::CodeCompletionRankingModel;
2070 CodeCompletion::Scores Scores;
2071 switch (Opts.RankingModel) {
2072 case RM::Heuristics:
2073 Scores.Quality = Quality.evaluateHeuristics();
2074 Scores.Relevance = Relevance.evaluateHeuristics();
2079 Scores.ExcludingName =
2080 Relevance.NameMatch > std::numeric_limits<float>::epsilon()
2081 ? Scores.Total / Relevance.NameMatch
2085 case RM::DecisionForest:
2086 DecisionForestScores DFScores = Opts.DecisionForestScorer(
2087 Quality, Relevance, Opts.DecisionForestBase);
2088 Scores.ExcludingName = DFScores.ExcludingName;
2089 Scores.Total = DFScores.Total;
2092 llvm_unreachable(
"Unhandled CodeCompletion ranking model.");
2096 void addCandidate(TopN<ScoredBundle, ScoredBundleGreater> &Candidates,
2097 CompletionCandidate::Bundle Bundle) {
2098 SymbolQualitySignals Quality;
2099 SymbolRelevanceSignals Relevance;
2100 Relevance.Context = CCContextKind;
2101 Relevance.Name = Bundle.front().Name;
2102 Relevance.FilterLength = HeuristicPrefix.Name.size();
2104 Relevance.FileProximityMatch = &*FileProximity;
2106 Relevance.ScopeProximityMatch = &*ScopeProximity;
2108 Relevance.HadContextType =
true;
2109 Relevance.ContextWords = &ContextWords;
2110 Relevance.MainFileSignals = Opts.MainFileSignals;
2112 auto &First = Bundle.front();
2113 if (
auto FuzzyScore = fuzzyScore(First))
2114 Relevance.NameMatch = *FuzzyScore;
2118 bool FromIndex =
false;
2119 for (
const auto &Candidate : Bundle) {
2120 if (Candidate.IndexResult) {
2121 Quality.merge(*Candidate.IndexResult);
2122 Relevance.merge(*Candidate.IndexResult);
2123 Origin |= Candidate.IndexResult->Origin;
2125 if (!Candidate.IndexResult->Type.empty())
2126 Relevance.HadSymbolType |=
true;
2127 if (PreferredType &&
2128 PreferredType->raw() == Candidate.IndexResult->Type) {
2129 Relevance.TypeMatchesPreferred =
true;
2132 if (Candidate.SemaResult) {
2133 Quality.merge(*Candidate.SemaResult);
2134 Relevance.merge(*Candidate.SemaResult);
2135 if (PreferredType) {
2137 Recorder->CCSema->getASTContext(), *Candidate.SemaResult)) {
2138 Relevance.HadSymbolType |=
true;
2139 if (PreferredType == CompletionType)
2140 Relevance.TypeMatchesPreferred =
true;
2145 if (Candidate.IdentifierResult) {
2146 Quality.References = Candidate.IdentifierResult->References;
2152 CodeCompletion::Scores Scores = evaluateCompletion(Quality, Relevance);
2153 if (Opts.RecordCCResult)
2154 Opts.RecordCCResult(toCodeCompletion(Bundle), Quality, Relevance,
2157 dlog(
"CodeComplete: {0} ({1}) = {2}\n{3}{4}\n", First.Name,
2158 llvm::to_string(Origin), Scores.Total, llvm::to_string(Quality),
2159 llvm::to_string(Relevance));
2162 NIndex += FromIndex;
2165 if (Candidates.push({std::move(Bundle), Scores}))
2169 CodeCompletion toCodeCompletion(
const CompletionCandidate::Bundle &Bundle) {
2170 std::optional<CodeCompletionBuilder> Builder;
2171 for (
const auto &Item : Bundle) {
2172 CodeCompletionString *SemaCCS =
2173 Item.SemaResult ? Recorder->codeCompletionString(*Item.SemaResult)
2176 Builder.emplace(Recorder ? &Recorder->CCSema->getASTContext() :
nullptr,
2177 Item, SemaCCS, AccessibleScopes, *Inserter, FileName,
2178 CCContextKind, Opts, IsUsingDeclaration, NextTokenKind);
2180 Builder->add(Item, SemaCCS, CCContextKind);
2182 return Builder->build();
2189 clang::CodeCompleteOptions
Result;
2190 Result.IncludeCodePatterns =
2192 Result.IncludeMacros =
true;
2193 Result.IncludeGlobals =
true;
2198 Result.IncludeBriefComments =
false;
2203 Result.LoadExternal = ForceLoadPreamble || !Index;
2204 Result.IncludeFixIts = IncludeFixIts;
2211 assert(Offset <= Content.size());
2212 StringRef Rest = Content.take_front(Offset);
2217 while (!Rest.empty() && isAsciiIdentifierContinue(Rest.back()))
2218 Rest = Rest.drop_back();
2219 Result.
Name = Content.slice(Rest.size(), Offset);
2222 while (Rest.consume_back(
"::") && !Rest.ends_with(
":"))
2223 while (!Rest.empty() && isAsciiIdentifierContinue(Rest.back()))
2224 Rest = Rest.drop_back();
2226 Content.slice(Rest.size(), Result.
Name.begin() - Content.begin());
2235 llvm::StringRef Prefix,
2239 return CodeCompleteResult();
2241 clang::CodeCompleteOptions Options;
2242 Options.IncludeGlobals =
false;
2243 Options.IncludeMacros =
false;
2244 Options.IncludeCodePatterns =
false;
2245 Options.IncludeBriefComments =
false;
2246 std::set<std::string> ParamNames;
2250 std::make_unique<ParamNameCollector>(Options, ParamNames), Options,
2254 if (ParamNames.empty())
2255 return CodeCompleteResult();
2257 CodeCompleteResult Result;
2258 Range CompletionRange;
2262 CompletionRange.
end =
2264 Result.CompletionRange = CompletionRange;
2265 Result.Context = CodeCompletionContext::CCC_NaturalLanguage;
2266 for (llvm::StringRef Name : ParamNames) {
2267 if (!Name.starts_with(Prefix))
2269 CodeCompletion Item;
2270 Item.Name = Name.str() +
"=*/";
2271 Item.FilterText = Item.Name;
2273 Item.CompletionTokenRange = CompletionRange;
2275 Result.Completions.push_back(Item);
2284std::optional<unsigned>
2286 while (!Content.empty() && isAsciiIdentifierContinue(Content.back()))
2287 Content = Content.drop_back();
2288 Content = Content.rtrim();
2289 if (Content.ends_with(
"/*"))
2290 return Content.size() - 2;
2291 return std::nullopt;
2298 SpeculativeFuzzyFind *SpecFuzzyFind) {
2301 elog(
"Code completion position was invalid {0}", Offset.takeError());
2302 return CodeCompleteResult();
2305 auto Content = llvm::StringRef(ParseInput.
Contents).take_front(*Offset);
2312 auto CommentPrefix = Content.substr(*OffsetBeforeComment + 2).trim();
2317 auto Flow = CodeCompleteFlow(
2319 SpecFuzzyFind, Opts);
2320 return (!
Preamble || Opts.RunParser == CodeCompleteOptions::NeverParse)
2321 ? std::move(Flow).runWithoutSema(ParseInput.
Contents, *Offset,
2323 : std::move(Flow).run({FileName, *Offset, *
Preamble,
2336 elog(
"Signature help position was invalid {0}", Offset.takeError());
2340 clang::CodeCompleteOptions Options;
2341 Options.IncludeGlobals =
false;
2342 Options.IncludeMacros =
false;
2343 Options.IncludeCodePatterns =
false;
2344 Options.IncludeBriefComments =
false;
2346 std::make_unique<SignatureHelpCollector>(Options, DocumentationFormat,
2347 ParseInput.
Index, Result),
2349 {FileName, *Offset, Preamble,
2350 PreamblePatch::createFullPatch(FileName, ParseInput, Preamble),
2356 auto InTopLevelScope = [](
const NamedDecl &ND) {
2357 switch (ND.getDeclContext()->getDeclKind()) {
2358 case Decl::TranslationUnit:
2359 case Decl::Namespace:
2360 case Decl::LinkageSpec:
2367 auto InClassScope = [](
const NamedDecl &ND) {
2368 return ND.getDeclContext()->getDeclKind() == Decl::CXXRecord;
2379 if (llvm::isa<ObjCCategoryDecl>(&ND) || llvm::isa<ObjCCategoryImplDecl>(&ND))
2382 if (InTopLevelScope(ND))
2388 if (
const auto *EnumDecl = dyn_cast<clang::EnumDecl>(ND.getDeclContext()))
2389 return (InTopLevelScope(*EnumDecl) || InClassScope(*EnumDecl));
2394CompletionItem CodeCompletion::render(
const CodeCompleteOptions &Opts)
const {
2396 const auto *InsertInclude = Includes.empty() ? nullptr : &Includes[0];
2399 LSP.label = ((InsertInclude && InsertInclude->Insertion)
2400 ? Opts.IncludeIndicator.Insert
2401 : Opts.IncludeIndicator.NoInsert) +
2402 (Opts.ShowOrigins ?
"[" + llvm::to_string(Origin) +
"]" :
"") +
2403 RequiredQualifier + Name;
2404 LSP.labelDetails.emplace();
2405 LSP.labelDetails->detail = Signature;
2408 LSP.detail = BundleSize > 1
2409 ? std::string(llvm::formatv(
"[{0} overloads]", BundleSize))
2414 if (InsertInclude || Documentation) {
2415 markup::Document Doc;
2417 Doc.addParagraph().appendText(
"From ").appendCode(InsertInclude->Header);
2419 Doc.append(*Documentation);
2420 LSP.documentation = renderDoc(Doc, Opts.DocumentationFormat);
2422 LSP.sortText =
sortText(Score.Total, FilterText);
2423 LSP.filterText = FilterText;
2424 LSP.textEdit = {CompletionTokenRange, RequiredQualifier + Name,
""};
2432 for (
const auto &FixIt : FixIts) {
2433 if (FixIt.range.end == LSP.textEdit->range.start) {
2434 LSP.textEdit->newText = FixIt.newText + LSP.textEdit->newText;
2435 LSP.textEdit->range.start = FixIt.range.start;
2437 LSP.additionalTextEdits.push_back(FixIt);
2440 if (Opts.EnableSnippets)
2441 LSP.textEdit->newText += SnippetSuffix;
2445 LSP.insertText = LSP.textEdit->newText;
2449 LSP.insertTextFormat = (Opts.EnableSnippets && !SnippetSuffix.empty())
2452 if (InsertInclude && InsertInclude->Insertion)
2453 LSP.additionalTextEdits.push_back(*InsertInclude->Insertion);
2455 LSP.score = Score.ExcludingName;
2460llvm::raw_ostream &
operator<<(llvm::raw_ostream &OS,
const CodeCompletion &C) {
2461 OS <<
"Signature: " <<
"\"" << C.Signature <<
"\", "
2462 <<
"SnippetSuffix: " <<
"\"" << C.SnippetSuffix <<
"\""
2469 const CodeCompleteResult &R) {
2470 OS <<
"CodeCompleteResult: " << R.Completions.size() << (R.HasMore ?
"+" :
"")
2471 <<
" (" << getCompletionKindString(R.Context) <<
")"
2473 for (
const auto &C : R.Completions)
2480 Line = Line.ltrim();
2481 if (!Line.consume_front(
"#"))
2483 Line = Line.ltrim();
2484 if (!(Line.consume_front(
"include_next") || Line.consume_front(
"include") ||
2485 Line.consume_front(
"import")))
2487 Line = Line.ltrim();
2488 if (Line.consume_front(
"<"))
2489 return Line.count(
'>') == 0;
2490 if (Line.consume_front(
"\""))
2491 return Line.count(
'"') == 0;
2497 Content = Content.take_front(Offset);
2498 auto Pos = Content.rfind(
'\n');
2499 if (Pos != llvm::StringRef::npos)
2500 Content = Content.substr(Pos + 1);
2503 if (Content.ends_with(
".") || Content.ends_with(
"->") ||
2504 Content.ends_with(
"::") || Content.ends_with(
"/*"))
2507 if ((Content.ends_with(
"<") || Content.ends_with(
"\"") ||
2508 Content.ends_with(
"/")) &&
2513 return !Content.empty() && (isAsciiIdentifierContinue(Content.back()) ||
2514 !llvm::isASCII(Content.back()));
static clang::FrontendPluginRegistry::Add< clang::tidy::ClangTidyPluginAction > X("clang-tidy", "clang-tidy")
#define SPAN_ATTACH(S, Name, Expr)
Attach a key-value pair to a Span event.
static std::optional< OpaqueType > fromCompletionResult(ASTContext &Ctx, const CodeCompletionResult &R)
Create a type from a code completion result.
static std::optional< OpaqueType > fromType(ASTContext &Ctx, QualType Type)
Construct an instance from a clang::QualType.
static PreamblePatch createMacroPatch(llvm::StringRef FileName, const ParseInputs &Modified, const PreambleData &Baseline)
static PreamblePatch createFullPatch(llvm::StringRef FileName, const ParseInputs &Modified, const PreambleData &Baseline)
Builds a patch that contains new PP directives introduced to the preamble section of Modified compare...
static llvm::Expected< std::string > resolve(const URI &U, llvm::StringRef HintPath="")
Resolves the absolute path of U.
std::pair< StringRef, StringRef > splitQualifiedName(StringRef QName)
@ Info
An information message.
SymbolID getSymbolID(const Decl *D)
Gets the symbol ID for a declaration. Returned SymbolID might be null.
std::string formatDocumentation(const CodeCompletionString &CCS, llvm::StringRef DocComment)
Assembles formatted documentation for a completion result.
Range halfOpenToRange(const SourceManager &SM, CharSourceRange R)
std::string sortText(float Score, llvm::StringRef Name)
Returns a string that sorts in the same order as (-Score, Tiebreak), for LSP.
std::string getDeclComment(const ASTContext &Ctx, const NamedDecl &Decl)
Similar to getDocComment, but returns the comment for a NamedDecl.
bool isIncludeFile(llvm::StringRef Line)
TextEdit toTextEdit(const FixItHint &FixIt, const SourceManager &M, const LangOptions &L)
Position offsetToPosition(llvm::StringRef Code, size_t Offset)
Turn an offset in Code into a [line, column] pair.
size_t lspLength(llvm::StringRef Code)
CompletionPrefix guessCompletionPrefix(llvm::StringRef Content, unsigned Offset)
std::unique_ptr< CompilerInvocation > buildCompilerInvocation(const ParseInputs &Inputs, clang::DiagnosticConsumer &D, std::vector< std::string > *CC1Args)
Builds compiler invocation that could be used to build AST or preamble.
bool isExplicitTemplateSpecialization(const NamedDecl *D)
Indicates if D is an explicit template specialization, e.g.
bool allowImplicitCompletion(llvm::StringRef Content, unsigned Offset)
void vlog(const char *Fmt, Ts &&... Vals)
static const char * toString(OffsetEncoding OE)
CodeCompleteResult codeCompleteComment(PathRef FileName, unsigned Offset, llvm::StringRef Prefix, const PreambleData *Preamble, const ParseInputs &ParseInput)
llvm::Error error(std::error_code EC, const char *Fmt, Ts &&... Vals)
llvm::raw_ostream & operator<<(llvm::raw_ostream &OS, const CodeCompletion &C)
std::string getReturnType(const CodeCompletionString &CCS)
Gets detail to be used as the detail field in an LSP completion item.
Position sourceLocToPosition(const SourceManager &SM, SourceLocation Loc)
Turn a SourceLocation into a [line, column] pair.
llvm::StringMap< unsigned > collectIdentifiers(llvm::StringRef Content, const format::FormatStyle &Style)
Collects identifiers with counts in the source code.
bool hasUnstableLinkage(const Decl *D)
Whether we must avoid computing linkage for D during code completion.
llvm::json::Value toJSON(const FuzzyFindRequest &Request)
std::vector< std::string > visibleNamespaces(llvm::StringRef Code, const LangOptions &LangOpts)
Heuristically determine namespaces visible at a point, without parsing Code.
llvm::Expected< HeaderFile > toHeaderFile(llvm::StringRef Header, llvm::StringRef HintPath)
Creates a HeaderFile from Header which can be either a URI or a literal include.
std::unique_ptr< CompilerInstance > prepareCompilerInstance(std::unique_ptr< clang::CompilerInvocation > CI, const PrecompiledPreamble *Preamble, std::unique_ptr< llvm::MemoryBuffer > Buffer, llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > VFS, DiagnosticConsumer &DiagsClient)
std::future< T > runAsync(llvm::unique_function< T()> Action)
Runs Action asynchronously with a new std::thread.
void log(const char *Fmt, Ts &&... Vals)
llvm::Expected< size_t > positionToOffset(llvm::StringRef Code, Position P, bool AllowColumnsBeyondLineLength)
Turn a [line, column] pair into an offset in Code.
std::optional< unsigned > maybeFunctionArgumentCommentStart(llvm::StringRef Content)
llvm::StringSet collectWords(llvm::StringRef Content)
Collects words from the source code.
void getSignature(const CodeCompletionString &CCS, std::string *Signature, std::string *Snippet, CodeCompletionResult::ResultKind ResultKind, CXCursorKind CursorKind, bool IncludeFunctionArguments, std::string *RequiredQualifiers)
Formats the signature for an item, as a display string and snippet.
llvm::StringRef PathRef
A typedef to represent a ref to file path.
llvm::SmallVector< SymbolInclude, 1 > getRankedIncludes(const Symbol &Sym)
std::pair< size_t, size_t > offsetToClangLineColumn(llvm::StringRef Code, size_t Offset)
@ Deprecated
Deprecated or obsolete code.
@ Full
Documents are synced by always sending the full content of the document.
void parseDocumentation(llvm::StringRef Input, markup::Document &Output)
float evaluateSymbolAndRelevance(float SymbolQuality, float SymbolRelevance)
Combine symbol quality and relevance into a single score.
CodeCompleteResult codeComplete(PathRef FileName, Position Pos, const PreambleData *Preamble, const ParseInputs &ParseInput, CodeCompleteOptions Opts, SpeculativeFuzzyFind *SpecFuzzyFind)
Gets code completions at a specified Pos in FileName.
@ PlainText
The primary text to be inserted is treated as a plain string.
@ Snippet
The primary text to be inserted is treated as a snippet.
std::string printQualifiedName(const NamedDecl &ND)
Returns the qualified name of ND.
SignatureHelp signatureHelp(PathRef FileName, Position Pos, const PreambleData &Preamble, const ParseInputs &ParseInput, MarkupKind DocumentationFormat)
Get signature help at a specified Pos in FileName.
void elog(const char *Fmt, Ts &&... Vals)
std::string getDocComment(const ASTContext &Ctx, const CodeCompletionResult &Result, bool CommentsFromHeaders)
Gets a minimally formatted documentation comment of Result, with comment markers stripped.
std::string printNamespaceScope(const DeclContext &DC)
Returns the first enclosing namespace scope starting from DC.
bool isIndexedForCodeCompletion(const NamedDecl &ND, ASTContext &ASTCtx)
format::FormatStyle getFormatStyleForFile(llvm::StringRef File, llvm::StringRef Content, const ThreadsafeFS &TFS, bool FormatFile)
Choose the clang-format style we should apply to a certain file.
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
clang::CodeCompleteOptions getClangCompleteOpts() const
Returns options that can be passed to clang's completion engine.
llvm::StringRef Qualifier
struct clang::clangd::Config::@314053012031341203055315320366267371313202370174 Style
Style of the codebase.
static const Config & current()
Returns the Config of the current Context, or an empty configuration.
ArgumentListsPolicy
controls the completion options for argument lists.
@ None
nothing, no argument list and also NO Delimiters "()" or "<>".
@ Delimiters
empty pair of delimiters "()" or "<>".
@ OpenDelimiter
open, only opening delimiter "(" or "<".
@ FullPlaceholders
full name of both type and variable.
@ PlainText
Treat comments as plain text.
std::vector< std::function< bool(llvm::StringRef)> > QuotedHeaders
CodePatternsPolicy CodePatterns
Enables code patterns & snippets suggestions.
CommentFormatPolicy CommentFormat
std::vector< std::function< bool(llvm::StringRef)> > AngledHeaders
The parsed preamble and associated data.
Position start
The range's start position.
Position end
The range's end position.
Represents the signature of a callable.
@ Deprecated
Indicates if the symbol is deprecated.
@ Include
#include "header.h"
@ Import
#import "header.h"