38 #include "clang/AST/Decl.h" 39 #include "clang/AST/DeclBase.h" 40 #include "clang/Basic/LangOptions.h" 41 #include "clang/Basic/SourceLocation.h" 42 #include "clang/Format/Format.h" 43 #include "clang/Frontend/CompilerInstance.h" 44 #include "clang/Frontend/FrontendActions.h" 45 #include "clang/Lex/PreprocessorOptions.h" 46 #include "clang/Sema/CodeCompleteConsumer.h" 47 #include "clang/Sema/Sema.h" 48 #include "llvm/ADT/ArrayRef.h" 49 #include "llvm/ADT/None.h" 50 #include "llvm/ADT/Optional.h" 51 #include "llvm/ADT/SmallVector.h" 52 #include "llvm/Support/Error.h" 53 #include "llvm/Support/Format.h" 54 #include "llvm/Support/FormatVariadic.h" 55 #include "llvm/Support/ScopedPrinter.h" 60 #define DEBUG_TYPE "CodeComplete" 73 case SK::NamespaceAlias:
94 case SK::ConversionFunction:
102 case SK::EnumConstant:
104 case SK::InstanceMethod:
105 case SK::ClassMethod:
106 case SK::StaticMethod:
109 case SK::InstanceProperty:
110 case SK::ClassProperty:
111 case SK::StaticProperty:
116 llvm_unreachable(
"Unhandled clang::index::SymbolKind.");
120 toCompletionItemKind(CodeCompletionResult::ResultKind ResKind,
121 const NamedDecl *Decl,
125 if (CtxKind == CodeCompletionContext::CCC_IncludedFile)
128 case CodeCompletionResult::RK_Declaration:
129 llvm_unreachable(
"RK_Declaration without Decl");
130 case CodeCompletionResult::RK_Keyword:
132 case CodeCompletionResult::RK_Macro:
135 case CodeCompletionResult::RK_Pattern:
138 llvm_unreachable(
"Unhandled CodeCompletionResult::ResultKind.");
144 std::string getOptionalParameters(
const CodeCompletionString &CCS,
145 std::vector<ParameterInformation> &Parameters,
146 SignatureQualitySignals &Signal) {
148 for (
const auto &Chunk : CCS) {
149 switch (Chunk.Kind) {
150 case CodeCompletionString::CK_Optional:
151 assert(Chunk.Optional &&
152 "Expected the optional code completion string to be non-null.");
153 Result += getOptionalParameters(*Chunk.Optional, Parameters, Signal);
155 case CodeCompletionString::CK_VerticalSpace:
157 case CodeCompletionString::CK_Placeholder:
161 case CodeCompletionString::CK_CurrentParameter: {
165 Result += Chunk.Text;
166 ParameterInformation
Info;
167 Info.label = Chunk.Text;
168 Parameters.push_back(std::move(Info));
169 Signal.ContainsActiveParameter =
true;
170 Signal.NumberOfOptionalParameters++;
174 Result += Chunk.Text;
183 static llvm::Expected<HeaderFile> toHeaderFile(llvm::StringRef Header,
184 llvm::StringRef HintPath) {
186 return HeaderFile{Header.str(),
true};
189 return U.takeError();
193 return IncludePath.takeError();
194 if (!IncludePath->empty())
195 return HeaderFile{std::move(*IncludePath),
true};
199 return Resolved.takeError();
200 return HeaderFile{std::move(*Resolved),
false};
205 struct CompletionCandidate {
214 size_t overloadSet()
const {
215 llvm::SmallString<256> Scratch;
217 switch (IndexResult->SymInfo.Kind) {
218 case index::SymbolKind::ClassMethod:
219 case index::SymbolKind::InstanceMethod:
220 case index::SymbolKind::StaticMethod:
222 llvm_unreachable(
"Don't expect members from index in code completion");
226 case index::SymbolKind::Function:
229 return llvm::hash_combine(
230 (IndexResult->Scope + IndexResult->Name).toStringRef(Scratch),
231 headerToInsertIfAllowed().getValueOr(
""));
238 const NamedDecl *
D = SemaResult->Declaration;
239 if (!D || !D->isFunctionOrFunctionTemplate())
242 llvm::raw_svector_ostream OS(Scratch);
243 D->printQualifiedName(OS);
245 return llvm::hash_combine(Scratch,
246 headerToInsertIfAllowed().getValueOr(
""));
250 llvm::Optional<llvm::StringRef> headerToInsertIfAllowed()
const {
251 if (RankedIncludeHeaders.empty())
253 if (SemaResult && SemaResult->Declaration) {
256 auto &SM = SemaResult->Declaration->getASTContext().getSourceManager();
257 for (
const Decl *RD : SemaResult->Declaration->redecls())
258 if (SM.isInMainFile(SM.getExpansionLoc(RD->getBeginLoc())))
261 return RankedIncludeHeaders[0];
264 using Bundle = llvm::SmallVector<CompletionCandidate, 4>;
267 std::pair<CompletionCandidate::Bundle, CodeCompletion::Scores>;
268 struct ScoredBundleGreater {
269 bool operator()(
const ScoredBundle &L,
const ScoredBundle &R) {
270 if (L.second.Total != R.second.Total)
271 return L.second.Total > R.second.Total;
272 return L.first.front().Name <
273 R.first.front().Name;
284 struct CodeCompletionBuilder {
285 CodeCompletionBuilder(ASTContext &ASTCtx,
const CompletionCandidate &C,
286 CodeCompletionString *SemaCCS,
287 llvm::ArrayRef<std::string> QueryScopes,
288 const IncludeInserter &Includes,
291 const CodeCompleteOptions &Opts)
292 : ASTCtx(ASTCtx), ExtractDocumentation(Opts.IncludeComments),
297 Completion.Name = llvm::StringRef(SemaCCS->getTypedText());
298 if (Completion.Scope.empty()) {
299 if ((C.SemaResult->Kind == CodeCompletionResult::RK_Declaration) ||
300 (C.SemaResult->Kind == CodeCompletionResult::RK_Pattern))
301 if (
const auto *
D = C.SemaResult->getDeclaration())
302 if (
const auto *ND = dyn_cast<NamedDecl>(
D))
306 Completion.Kind = toCompletionItemKind(
307 C.SemaResult->Kind, C.SemaResult->Declaration, ContextKind);
311 Completion.Name.back() ==
'/')
313 for (
const auto &
FixIt : C.SemaResult->FixIts) {
314 Completion.FixIts.push_back(
317 llvm::sort(Completion.FixIts, [](
const TextEdit &
X,
const TextEdit &Y) {
318 return std::tie(X.range.start.line, X.range.start.character) <
319 std::tie(Y.range.start.line, Y.range.start.character);
321 Completion.Deprecated |=
322 (C.SemaResult->Availability == CXAvailability_Deprecated);
325 Completion.Origin |= C.IndexResult->Origin;
326 if (Completion.Scope.empty())
327 Completion.Scope = C.IndexResult->Scope;
329 Completion.Kind = toCompletionItemKind(C.IndexResult->SymInfo.Kind);
330 if (Completion.Name.empty())
331 Completion.Name = C.IndexResult->Name;
334 if (Completion.RequiredQualifier.empty() && !C.SemaResult) {
335 llvm::StringRef ShortestQualifier = C.IndexResult->Scope;
336 for (llvm::StringRef Scope : QueryScopes) {
337 llvm::StringRef Qualifier = C.IndexResult->Scope;
338 if (Qualifier.consume_front(Scope) &&
339 Qualifier.size() < ShortestQualifier.size())
340 ShortestQualifier = Qualifier;
342 Completion.RequiredQualifier = ShortestQualifier;
348 auto Inserted = [&](llvm::StringRef Header)
349 -> llvm::Expected<std::pair<std::string, bool>> {
350 auto ResolvedDeclaring =
351 toHeaderFile(C.IndexResult->CanonicalDeclaration.FileURI, FileName);
352 if (!ResolvedDeclaring)
353 return ResolvedDeclaring.takeError();
354 auto ResolvedInserted = toHeaderFile(Header, FileName);
355 if (!ResolvedInserted)
356 return ResolvedInserted.takeError();
357 return std::make_pair(
358 Includes.calculateIncludePath(*ResolvedDeclaring, *ResolvedInserted),
359 Includes.shouldInsertInclude(*ResolvedDeclaring, *ResolvedInserted));
361 bool ShouldInsert = C.headerToInsertIfAllowed().hasValue();
363 for (
const auto &Inc : C.RankedIncludeHeaders) {
364 if (
auto ToInclude = Inserted(Inc)) {
365 CodeCompletion::IncludeCandidate Include;
366 Include.Header = ToInclude->first;
367 if (ToInclude->second && ShouldInsert)
368 Include.Insertion = Includes.insert(ToInclude->first);
369 Completion.Includes.push_back(std::move(Include));
371 log(
"Failed to generate include insertion edits for adding header " 372 "(FileURI='{0}', IncludeHeader='{1}') into {2}",
373 C.IndexResult->CanonicalDeclaration.FileURI, Inc, FileName);
376 std::stable_partition(Completion.Includes.begin(),
377 Completion.Includes.end(),
378 [](
const CodeCompletion::IncludeCandidate &I) {
379 return !I.Insertion.hasValue();
383 void add(
const CompletionCandidate &C, CodeCompletionString *SemaCCS) {
384 assert(
bool(C.SemaResult) ==
bool(SemaCCS));
386 BundledEntry &S =
Bundled.back();
389 &Completion.RequiredQualifier);
391 }
else if (C.IndexResult) {
392 S.Signature = C.IndexResult->Signature;
393 S.SnippetSuffix = C.IndexResult->CompletionSnippetSuffix;
394 S.ReturnType = C.IndexResult->ReturnType;
396 if (ExtractDocumentation && Completion.Documentation.empty()) {
398 Completion.Documentation = C.IndexResult->Documentation;
399 else if (C.SemaResult)
400 Completion.Documentation =
getDocComment(ASTCtx, *C.SemaResult,
405 CodeCompletion build() {
406 Completion.ReturnType = summarizeReturnType();
407 Completion.Signature = summarizeSignature();
408 Completion.SnippetSuffix = summarizeSnippet();
409 Completion.BundleSize =
Bundled.size();
410 return std::move(Completion);
414 struct BundledEntry {
421 template <std::
string BundledEntry::*Member>
422 const std::string *onlyValue()
const {
424 for (
auto I = B + 1; I != E; ++I)
425 if (I->*Member != B->*Member)
427 return &(B->*Member);
430 template <
bool BundledEntry::*Member>
const bool *onlyValue()
const {
432 for (
auto I = B + 1; I != E; ++I)
433 if (I->*Member != B->*Member)
435 return &(B->*Member);
438 std::string summarizeReturnType()
const {
439 if (
auto *RT = onlyValue<&BundledEntry::ReturnType>())
444 std::string summarizeSnippet()
const {
445 auto *
Snippet = onlyValue<&BundledEntry::SnippetSuffix>();
467 bool EmptyArgs = llvm::StringRef(*Snippet).endswith(
"()");
469 return EmptyArgs ?
"<$1>()$0" :
"<$1>($0)";
471 return EmptyArgs ?
"()" :
"($0)";
481 if (llvm::StringRef(*Snippet).endswith(
"<>"))
488 std::string summarizeSignature()
const {
489 if (
auto *
Signature = onlyValue<&BundledEntry::Signature>())
496 CodeCompletion Completion;
497 llvm::SmallVector<BundledEntry, 1>
Bundled;
498 bool ExtractDocumentation;
503 llvm::Optional<SymbolID>
getSymbolID(
const CodeCompletionResult &R,
504 const SourceManager &SM) {
506 case CodeCompletionResult::RK_Declaration:
507 case CodeCompletionResult::RK_Pattern: {
510 case CodeCompletionResult::RK_Macro:
512 case CodeCompletionResult::RK_Keyword:
515 llvm_unreachable(
"unknown CodeCompletionResult kind");
520 struct SpecifiedScope {
548 std::vector<std::string> scopesForIndexQuery() {
550 for (llvm::StringRef AS : AccessibleScopes)
552 ((UnresolvedQualifier ? *UnresolvedQualifier :
"") + AS).str());
553 return {Results.begin(), Results.end()};
560 std::pair<std::vector<std::string>,
bool>
562 const CodeCompleteOptions &Opts) {
563 auto GetAllAccessibleScopes = [](CodeCompletionContext &
CCContext) {
565 for (
auto *Context : CCContext.getVisitedContexts()) {
566 if (isa<TranslationUnitDecl>(Context))
567 Info.AccessibleScopes.push_back(
"");
568 else if (isa<NamespaceDecl>(Context))
574 auto SS = CCContext.getCXXScopeSpecifier();
578 std::vector<std::string> Scopes;
580 Scopes.push_back(EnclosingScope);
581 for (
auto &S : GetAllAccessibleScopes(CCContext).scopesForIndexQuery()) {
582 if (EnclosingScope != S)
583 Scopes.push_back(std::move(S));
586 return {Scopes, Opts.AllScopes};
591 if ((*SS)->isValid()) {
592 return {GetAllAccessibleScopes(CCContext).scopesForIndexQuery(),
false};
600 Info.AccessibleScopes.push_back(
"");
602 Info.UnresolvedQualifier =
603 Lexer::getSourceText(CharSourceRange::getCharRange((*SS)->getRange()),
604 CCSema.SourceMgr, clang::LangOptions())
607 if (!Info.UnresolvedQualifier->empty())
608 *Info.UnresolvedQualifier +=
"::";
610 return {Info.scopesForIndexQuery(),
false};
617 case CodeCompletionContext::CCC_TopLevel:
618 case CodeCompletionContext::CCC_ObjCInterface:
619 case CodeCompletionContext::CCC_ObjCImplementation:
620 case CodeCompletionContext::CCC_ObjCIvarList:
621 case CodeCompletionContext::CCC_ClassStructUnion:
622 case CodeCompletionContext::CCC_Statement:
623 case CodeCompletionContext::CCC_Expression:
624 case CodeCompletionContext::CCC_ObjCMessageReceiver:
625 case CodeCompletionContext::CCC_EnumTag:
626 case CodeCompletionContext::CCC_UnionTag:
627 case CodeCompletionContext::CCC_ClassOrStructTag:
628 case CodeCompletionContext::CCC_ObjCProtocolName:
629 case CodeCompletionContext::CCC_Namespace:
630 case CodeCompletionContext::CCC_Type:
631 case CodeCompletionContext::CCC_ParenthesizedExpression:
632 case CodeCompletionContext::CCC_ObjCInterfaceName:
633 case CodeCompletionContext::CCC_ObjCCategoryName:
634 case CodeCompletionContext::CCC_Symbol:
635 case CodeCompletionContext::CCC_SymbolOrNewName:
637 case CodeCompletionContext::CCC_OtherWithMacros:
638 case CodeCompletionContext::CCC_DotMemberAccess:
639 case CodeCompletionContext::CCC_ArrowMemberAccess:
640 case CodeCompletionContext::CCC_ObjCPropertyAccess:
641 case CodeCompletionContext::CCC_MacroName:
642 case CodeCompletionContext::CCC_MacroNameUse:
643 case CodeCompletionContext::CCC_PreprocessorExpression:
644 case CodeCompletionContext::CCC_PreprocessorDirective:
645 case CodeCompletionContext::CCC_SelectorName:
646 case CodeCompletionContext::CCC_TypeQualifiers:
647 case CodeCompletionContext::CCC_ObjCInstanceMessage:
648 case CodeCompletionContext::CCC_ObjCClassMessage:
649 case CodeCompletionContext::CCC_IncludedFile:
651 case CodeCompletionContext::CCC_Other:
652 case CodeCompletionContext::CCC_NaturalLanguage:
653 case CodeCompletionContext::CCC_Recovery:
654 case CodeCompletionContext::CCC_NewName:
657 llvm_unreachable(
"unknown code completion context");
660 static bool isInjectedClass(
const NamedDecl &
D) {
661 if (
auto *R = dyn_cast_or_null<RecordDecl>(&D))
662 if (R->isInjectedClassName())
668 static bool isBlacklistedMember(
const NamedDecl &D) {
671 if (D.getKind() == Decl::CXXDestructor)
674 if (isInjectedClass(D))
677 auto NameKind = D.getDeclName().getNameKind();
678 if (NameKind == DeclarationName::CXXOperatorName ||
679 NameKind == DeclarationName::CXXLiteralOperatorName ||
680 NameKind == DeclarationName::CXXConversionFunctionName)
691 struct CompletionRecorder :
public CodeCompleteConsumer {
692 CompletionRecorder(
const CodeCompleteOptions &Opts,
693 llvm::unique_function<
void()> ResultsCallback)
694 : CodeCompleteConsumer(Opts.getClangCompleteOpts(),
696 CCContext(CodeCompletionContext::CCC_Other), Opts(Opts),
697 CCAllocator(std::make_shared<GlobalCodeCompletionAllocator>()),
698 CCTUInfo(CCAllocator), ResultsCallback(std::move(ResultsCallback)) {
699 assert(this->ResultsCallback);
707 void ProcessCodeCompleteResults(
class Sema &S, CodeCompletionContext Context,
708 CodeCompletionResult *InResults,
709 unsigned NumResults)
override final {
718 if (Context.getKind() == CodeCompletionContext::CCC_Recovery) {
719 log(
"Code complete: Ignoring sema code complete callback with Recovery " 726 if (NumResults == 0 && !contextAllowsIndex(Context.getKind()))
729 log(
"Multiple code complete callbacks (parser backtracked?). " 730 "Dropping results from context {0}, keeping results from {1}.",
731 getCompletionKindString(Context.getKind()),
732 getCompletionKindString(this->CCContext.getKind()));
740 for (
unsigned I = 0; I < NumResults; ++I) {
741 auto &
Result = InResults[I];
744 Result.Declaration->isCXXClassMember())
746 if (!Opts.IncludeIneligibleResults &&
747 (
Result.Availability == CXAvailability_NotAvailable ||
748 Result.Availability == CXAvailability_NotAccessible))
751 !Context.getBaseType().isNull()
752 && isBlacklistedMember(*
Result.Declaration))
756 if (
Result.Declaration && !Context.getCXXScopeSpecifier().hasValue() &&
757 isInjectedClass(*
Result.Declaration))
760 Result.StartsNestedNameSpecifier =
false;
761 Results.push_back(
Result);
766 CodeCompletionAllocator &getAllocator()
override {
return *CCAllocator; }
767 CodeCompletionTUInfo &getCodeCompletionTUInfo()
override {
return CCTUInfo; }
771 llvm::StringRef getName(
const CodeCompletionResult &
Result) {
772 switch (Result.Kind) {
773 case CodeCompletionResult::RK_Declaration:
774 if (
auto *ID = Result.Declaration->getIdentifier())
775 return ID->getName();
777 case CodeCompletionResult::RK_Keyword:
778 return Result.Keyword;
779 case CodeCompletionResult::RK_Macro:
780 return Result.Macro->getName();
781 case CodeCompletionResult::RK_Pattern:
782 return Result.Pattern->getTypedText();
784 auto *CCS = codeCompletionString(Result);
785 return CCS->getTypedText();
790 CodeCompletionString *codeCompletionString(
const CodeCompletionResult &R) {
792 return const_cast<CodeCompletionResult &
>(R).CreateCodeCompletionString(
793 *CCSema, CCContext, *CCAllocator, CCTUInfo,
798 CodeCompleteOptions Opts;
799 std::shared_ptr<GlobalCodeCompletionAllocator> CCAllocator;
800 CodeCompletionTUInfo CCTUInfo;
801 llvm::unique_function<void()> ResultsCallback;
804 struct ScoredSignature {
812 class SignatureHelpCollector final :
public CodeCompleteConsumer {
814 SignatureHelpCollector(
const clang::CodeCompleteOptions &CodeCompleteOpts,
815 const SymbolIndex *
Index, SignatureHelp &SigHelp)
816 : CodeCompleteConsumer(CodeCompleteOpts,
819 Allocator(std::make_shared<clang::GlobalCodeCompletionAllocator>()),
820 CCTUInfo(Allocator),
Index(Index) {}
822 void ProcessOverloadCandidates(Sema &S,
unsigned CurrentArg,
823 OverloadCandidate *Candidates,
824 unsigned NumCandidates,
825 SourceLocation OpenParLoc)
override {
826 assert(!OpenParLoc.isInvalid());
827 SourceManager &SrcMgr = S.getSourceManager();
828 OpenParLoc = SrcMgr.getFileLoc(OpenParLoc);
829 if (SrcMgr.isInMainFile(OpenParLoc))
832 elog(
"Location oustide main file in signature help: {0}",
833 OpenParLoc.printToString(SrcMgr));
835 std::vector<ScoredSignature> ScoredSignatures;
836 SigHelp.signatures.reserve(NumCandidates);
837 ScoredSignatures.reserve(NumCandidates);
841 SigHelp.activeSignature = 0;
842 assert(CurrentArg <= (
unsigned)std::numeric_limits<int>::max() &&
843 "too many arguments");
844 SigHelp.activeParameter =
static_cast<int>(CurrentArg);
845 for (
unsigned I = 0; I < NumCandidates; ++I) {
846 OverloadCandidate Candidate = Candidates[I];
850 if (
auto *Func = Candidate.getFunction()) {
851 if (
auto *Pattern = Func->getTemplateInstantiationPattern())
852 Candidate = OverloadCandidate(Pattern);
855 const auto *CCS = Candidate.CreateSignatureString(
856 CurrentArg, S, *Allocator, CCTUInfo,
true);
857 assert(CCS &&
"Expected the CodeCompletionString to be non-null");
858 ScoredSignatures.push_back(processOverloadCandidate(
860 Candidate.getFunction()
867 llvm::DenseMap<SymbolID, std::string> FetchedDocs;
869 LookupRequest IndexRequest;
870 for (
const auto &S : ScoredSignatures) {
873 IndexRequest.IDs.insert(*S.IDForDoc);
875 Index->lookup(IndexRequest, [&](
const Symbol &S) {
876 if (!S.Documentation.empty())
877 FetchedDocs[S.ID] = S.Documentation;
879 log(
"SigHelp: requested docs for {0} symbols from the index, got {1} " 880 "symbols with non-empty docs in the response",
881 IndexRequest.IDs.size(), FetchedDocs.size());
884 llvm::sort(ScoredSignatures, [](
const ScoredSignature &L,
885 const ScoredSignature &R) {
893 if (L.Quality.NumberOfParameters != R.Quality.NumberOfParameters)
894 return L.Quality.NumberOfParameters < R.Quality.NumberOfParameters;
895 if (L.Quality.NumberOfOptionalParameters !=
896 R.Quality.NumberOfOptionalParameters)
897 return L.Quality.NumberOfOptionalParameters <
898 R.Quality.NumberOfOptionalParameters;
899 if (L.Quality.Kind != R.Quality.Kind) {
900 using OC = CodeCompleteConsumer::OverloadCandidate;
901 switch (L.Quality.Kind) {
902 case OC::CK_Function:
904 case OC::CK_FunctionType:
905 return R.Quality.Kind != OC::CK_Function;
906 case OC::CK_FunctionTemplate:
909 llvm_unreachable(
"Unknown overload candidate type.");
911 if (L.Signature.label.size() != R.Signature.label.size())
912 return L.Signature.label.size() < R.Signature.label.size();
913 return L.Signature.label < R.Signature.label;
916 for (
auto &SS : ScoredSignatures) {
918 SS.IDForDoc ? FetchedDocs.find(*SS.IDForDoc) : FetchedDocs.end();
919 if (IndexDocIt != FetchedDocs.end())
920 SS.Signature.documentation = IndexDocIt->second;
922 SigHelp.signatures.push_back(std::move(SS.Signature));
926 GlobalCodeCompletionAllocator &getAllocator()
override {
return *Allocator; }
928 CodeCompletionTUInfo &getCodeCompletionTUInfo()
override {
return CCTUInfo; }
933 ScoredSignature processOverloadCandidate(
const OverloadCandidate &Candidate,
934 const CodeCompletionString &CCS,
935 llvm::StringRef DocComment)
const {
937 SignatureQualitySignals Signal;
941 Signal.Kind = Candidate.getKind();
943 for (
const auto &Chunk : CCS) {
944 switch (Chunk.Kind) {
945 case CodeCompletionString::CK_ResultType:
948 assert(!ReturnType &&
"Unexpected CK_ResultType");
949 ReturnType = Chunk.Text;
951 case CodeCompletionString::CK_Placeholder:
955 case CodeCompletionString::CK_CurrentParameter: {
959 Signature.label += Chunk.Text;
960 ParameterInformation
Info;
961 Info.label = Chunk.Text;
962 Signature.parameters.push_back(std::move(Info));
963 Signal.NumberOfParameters++;
964 Signal.ContainsActiveParameter =
true;
967 case CodeCompletionString::CK_Optional: {
969 assert(Chunk.Optional &&
970 "Expected the optional code completion string to be non-null.");
971 Signature.label += getOptionalParameters(*Chunk.Optional,
972 Signature.parameters, Signal);
975 case CodeCompletionString::CK_VerticalSpace:
978 Signature.label += Chunk.Text;
983 Signature.label +=
" -> ";
986 dlog(
"Signal for {0}: {1}", Signature, Signal);
988 Result.Signature = std::move(Signature);
989 Result.Quality = Signal;
991 Result.Signature.documentation.empty() && Candidate.getFunction()
997 SignatureHelp &SigHelp;
998 std::shared_ptr<clang::GlobalCodeCompletionAllocator> Allocator;
999 CodeCompletionTUInfo CCTUInfo;
1000 const SymbolIndex *
Index;
1003 struct SemaCompleteInput {
1009 llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
VFS;
1010 std::shared_ptr<PCHContainerOperations>
PCHs;
1015 bool semaCodeComplete(std::unique_ptr<CodeCompleteConsumer> Consumer,
1016 const clang::CodeCompleteOptions &Options,
1017 const SemaCompleteInput &Input,
1018 IncludeStructure *Includes =
nullptr) {
1019 trace::Span Tracer(
"Sema completion");
1020 std::vector<const char *> ArgStrs;
1021 for (
const auto &S : Input.Command.CommandLine)
1022 ArgStrs.push_back(S.c_str());
1024 if (Input.VFS->setCurrentWorkingDirectory(Input.Command.Directory)) {
1025 log(
"Couldn't set working directory");
1030 llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
VFS = Input.VFS;
1031 if (Input.Preamble && Input.Preamble->StatCache)
1032 VFS = Input.Preamble->StatCache->getConsumingFS(std::move(VFS));
1033 IgnoreDiagnostics DummyDiagsConsumer;
1034 auto CI = createInvocationFromCommandLine(
1036 CompilerInstance::createDiagnostics(
new DiagnosticOptions,
1037 &DummyDiagsConsumer,
false),
1040 elog(
"Couldn't create CompilerInvocation");
1043 auto &FrontendOpts = CI->getFrontendOpts();
1044 FrontendOpts.DisableFree =
false;
1045 FrontendOpts.SkipFunctionBodies =
true;
1046 CI->getLangOpts()->CommentOpts.ParseAllComments =
true;
1048 CI->getLangOpts()->SpellChecking =
false;
1050 FrontendOpts.CodeCompleteOpts = Options;
1051 FrontendOpts.CodeCompletionAt.FileName = Input.FileName;
1054 elog(
"Code completion position was invalid {0}", Offset.takeError());
1057 std::tie(FrontendOpts.CodeCompletionAt.Line,
1058 FrontendOpts.CodeCompletionAt.Column) =
1061 std::unique_ptr<llvm::MemoryBuffer> ContentsBuffer =
1062 llvm::MemoryBuffer::getMemBufferCopy(Input.Contents, Input.FileName);
1064 CI->getDiagnosticOpts().IgnoreWarnings =
true;
1071 bool CompletingInPreamble =
1072 ComputePreambleBounds(*CI->getLangOpts(), ContentsBuffer.get(), 0).Size >
1078 (Input.Preamble && !CompletingInPreamble) ? &Input.Preamble->Preamble
1080 std::move(ContentsBuffer), std::move(Input.PCHs), std::move(VFS),
1081 DummyDiagsConsumer);
1082 Clang->getPreprocessorOpts().SingleFileParseMode = CompletingInPreamble;
1083 Clang->setCodeCompletionConsumer(Consumer.release());
1086 if (!Action.BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0])) {
1087 log(
"BeginSourceFile() failed when running codeComplete for {0}",
1092 Clang->getPreprocessor().addPPCallbacks(
1094 if (!Action.Execute()) {
1095 log(
"Execute() failed when running codeComplete for {0}", Input.FileName);
1098 Action.EndSourceFile();
1104 bool allowIndex(CodeCompletionContext &CC) {
1105 if (!contextAllowsIndex(CC.getKind()))
1108 auto Scope = CC.getCXXScopeSpecifier();
1111 NestedNameSpecifier *NameSpec = (*Scope)->getScopeRep();
1116 switch (NameSpec->getKind()) {
1117 case NestedNameSpecifier::Global:
1119 case NestedNameSpecifier::NamespaceAlias:
1121 case NestedNameSpecifier::Super:
1122 case NestedNameSpecifier::TypeSpec:
1123 case NestedNameSpecifier::TypeSpecWithTemplate:
1125 case NestedNameSpecifier::Identifier:
1128 llvm_unreachable(
"invalid NestedNameSpecifier kind");
1131 std::future<SymbolSlab> startAsyncFuzzyFind(
const SymbolIndex &
Index,
1132 const FuzzyFindRequest &Req) {
1133 return runAsync<SymbolSlab>([&
Index, Req]() {
1134 trace::Span Tracer(
"Async fuzzyFind");
1135 SymbolSlab::Builder Syms;
1136 Index.fuzzyFind(Req, [&Syms](
const Symbol &Sym) { Syms.insert(Sym); });
1137 return std::move(Syms).build();
1144 llvm::Optional<FuzzyFindRequest>
1145 speculativeFuzzyFindRequestForCompletion(FuzzyFindRequest CachedReq,
1150 elog(
"Failed to speculate filter text for code completion at Pos " 1152 Pos.line, Pos.character, Filter.takeError());
1155 CachedReq.Query = *Filter;
1162 llvm::SmallVector<llvm::StringRef, 1> getRankedIncludes(
const Symbol &Sym) {
1163 auto Includes = Sym.IncludeHeaders;
1165 llvm::sort(Includes, [](
const Symbol::IncludeHeaderWithReferences &LHS,
1166 const Symbol::IncludeHeaderWithReferences &RHS) {
1167 if (LHS.References == RHS.References)
1168 return LHS.IncludeHeader.size() < RHS.IncludeHeader.size();
1169 return LHS.References > RHS.References;
1171 llvm::SmallVector<llvm::StringRef, 1> Headers;
1172 for (
const auto &Include : Includes)
1173 Headers.push_back(Include.IncludeHeader);
1206 class CodeCompleteFlow {
1208 IncludeStructure Includes;
1209 SpeculativeFuzzyFind *SpecFuzzyFind;
1210 const CodeCompleteOptions &Opts;
1213 CompletionRecorder *Recorder =
nullptr;
1214 int NSema = 0, NIndex = 0, NBoth = 0;
1215 bool Incomplete =
false;
1216 llvm::Optional<FuzzyMatcher> Filter;
1217 std::vector<std::string> QueryScopes;
1219 llvm::Optional<ScopeDistance> ScopeProximity;
1220 llvm::Optional<OpaqueType> PreferredType;
1222 bool AllScopes =
false;
1225 llvm::Optional<IncludeInserter> Inserter;
1226 llvm::Optional<URIDistance> FileProximity;
1231 llvm::Optional<FuzzyFindRequest> SpecReq;
1235 CodeCompleteFlow(
PathRef FileName,
const IncludeStructure &Includes,
1236 SpeculativeFuzzyFind *SpecFuzzyFind,
1237 const CodeCompleteOptions &Opts)
1238 :
FileName(FileName), Includes(Includes), SpecFuzzyFind(SpecFuzzyFind),
1241 CodeCompleteResult run(
const SemaCompleteInput &SemaCCInput) && {
1242 trace::Span Tracer(
"CodeCompleteFlow");
1243 if (Opts.Index && SpecFuzzyFind && SpecFuzzyFind->CachedReq.hasValue()) {
1244 assert(!SpecFuzzyFind->Result.valid());
1245 if ((SpecReq = speculativeFuzzyFindRequestForCompletion(
1246 *SpecFuzzyFind->CachedReq, SemaCCInput.FileName,
1247 SemaCCInput.Contents, SemaCCInput.Pos)))
1248 SpecFuzzyFind->Result = startAsyncFuzzyFind(*Opts.Index, *SpecReq);
1254 CodeCompleteResult Output;
1255 auto RecorderOwner = llvm::make_unique<CompletionRecorder>(Opts, [&]() {
1256 assert(Recorder &&
"Recorder is not set");
1258 format::getStyle(format::DefaultFormatStyle, SemaCCInput.FileName,
1259 format::DefaultFallbackStyle, SemaCCInput.Contents,
1260 SemaCCInput.VFS.get());
1262 log(
"getStyle() failed for file {0}: {1}. Fallback is LLVM style.",
1263 SemaCCInput.FileName, Style.takeError());
1264 Style = format::getLLVMStyle();
1269 SemaCCInput.FileName, SemaCCInput.Contents, *Style,
1270 SemaCCInput.Command.Directory,
1271 Recorder->CCSema->getPreprocessor().getHeaderSearchInfo());
1272 for (
const auto &Inc : Includes.MainFileIncludes)
1273 Inserter->addExisting(Inc);
1279 FileDistanceOptions ProxOpts{};
1280 const auto &SM = Recorder->CCSema->getSourceManager();
1281 llvm::StringMap<SourceParams> ProxSources;
1282 for (
auto &
Entry : Includes.includeDepth(
1283 SM.getFileEntryForID(SM.getMainFileID())->getName())) {
1284 auto &Source = ProxSources[
Entry.getKey()];
1285 Source.Cost =
Entry.getValue() * ProxOpts.IncludeCost;
1289 if (
Entry.getValue() > 0)
1290 Source.MaxUpTraversals = 1;
1292 FileProximity.emplace(ProxSources, ProxOpts);
1294 Output = runWithSema();
1297 getCompletionKindString(Recorder->CCContext.getKind()));
1298 log(
"Code complete: sema context {0}, query scopes [{1}] (AnyScope={2}), " 1299 "expected type {3}",
1300 getCompletionKindString(Recorder->CCContext.getKind()),
1301 llvm::join(QueryScopes.begin(), QueryScopes.end(),
","), AllScopes,
1302 PreferredType ? Recorder->CCContext.getPreferredType().getAsString()
1306 Recorder = RecorderOwner.get();
1308 semaCodeComplete(std::move(RecorderOwner), Opts.getClangCompleteOpts(),
1309 SemaCCInput, &Includes);
1314 SPAN_ATTACH(Tracer,
"returned_results", int64_t(Output.Completions.size()));
1315 SPAN_ATTACH(Tracer,
"incomplete", Output.HasMore);
1316 log(
"Code complete: {0} results from Sema, {1} from Index, " 1317 "{2} matched, {3} returned{4}.",
1318 NSema, NIndex, NBoth, Output.Completions.size(),
1319 Output.HasMore ?
" (incomplete)" :
"");
1320 assert(!Opts.Limit || Output.Completions.size() <= Opts.Limit);
1329 CodeCompleteResult runWithSema() {
1330 const auto &CodeCompletionRange = CharSourceRange::getCharRange(
1331 Recorder->CCSema->getPreprocessor().getCodeCompletionTokenRange());
1332 Range TextEditRange;
1338 if (CodeCompletionRange.isValid()) {
1340 CodeCompletionRange);
1343 Recorder->CCSema->getSourceManager(),
1344 Recorder->CCSema->getPreprocessor().getCodeCompletionLoc());
1345 TextEditRange.start = TextEditRange.end =
Pos;
1347 Filter = FuzzyMatcher(
1348 Recorder->CCSema->getPreprocessor().getCodeCompletionFilter());
1349 std::tie(QueryScopes, AllScopes) =
1350 getQueryScopes(Recorder->CCContext, *Recorder->CCSema, Opts);
1351 if (!QueryScopes.empty())
1352 ScopeProximity.emplace(QueryScopes);
1355 Recorder->CCContext.getPreferredType());
1361 auto IndexResults = (Opts.Index && allowIndex(Recorder->CCContext))
1364 trace::Span Tracer(
"Populate CodeCompleteResult");
1366 auto Top = mergeResults(Recorder->Results, IndexResults);
1367 CodeCompleteResult Output;
1370 for (
auto &C : Top) {
1371 Output.Completions.push_back(toCodeCompletion(C.first));
1372 Output.Completions.back().Score = C.second;
1373 Output.Completions.back().CompletionTokenRange = TextEditRange;
1375 Output.HasMore = Incomplete;
1376 Output.Context = Recorder->CCContext.getKind();
1381 SymbolSlab queryIndex() {
1382 trace::Span Tracer(
"Query index");
1383 SPAN_ATTACH(Tracer,
"limit", int64_t(Opts.Limit));
1386 FuzzyFindRequest Req;
1388 Req.Limit = Opts.Limit;
1389 Req.Query = Filter->pattern();
1390 Req.RestrictForCodeCompletion =
true;
1391 Req.Scopes = QueryScopes;
1392 Req.AnyScope = AllScopes;
1394 Req.ProximityPaths.push_back(FileName);
1395 vlog(
"Code complete: fuzzyFind({0:2})",
toJSON(Req));
1398 SpecFuzzyFind->NewReq = Req;
1399 if (SpecFuzzyFind && SpecFuzzyFind->Result.valid() && (*SpecReq == Req)) {
1400 vlog(
"Code complete: speculative fuzzy request matches the actual index " 1401 "request. Waiting for the speculative index results.");
1404 trace::Span WaitSpec(
"Wait speculative results");
1405 return SpecFuzzyFind->Result.get();
1408 SPAN_ATTACH(Tracer,
"Speculative results",
false);
1411 SymbolSlab::Builder ResultsBuilder;
1412 if (Opts.Index->fuzzyFind(
1413 Req, [&](
const Symbol &Sym) { ResultsBuilder.insert(Sym); }))
1415 return std::move(ResultsBuilder).build();
1421 std::vector<ScoredBundle>
1422 mergeResults(
const std::vector<CodeCompletionResult> &SemaResults,
1423 const SymbolSlab &IndexResults) {
1424 trace::Span Tracer(
"Merge and score results");
1425 std::vector<CompletionCandidate::Bundle> Bundles;
1426 llvm::DenseMap<size_t, size_t> BundleLookup;
1427 auto AddToBundles = [&](
const CodeCompletionResult *
SemaResult,
1429 CompletionCandidate C;
1433 C.RankedIncludeHeaders = getRankedIncludes(*C.IndexResult);
1435 if (
auto OverloadSet = Opts.BundleOverloads ? C.overloadSet() : 0) {
1436 auto Ret = BundleLookup.try_emplace(OverloadSet, Bundles.size());
1438 Bundles.emplace_back();
1439 Bundles[Ret.first->second].push_back(std::move(C));
1441 Bundles.emplace_back();
1442 Bundles.back().push_back(std::move(C));
1445 llvm::DenseSet<const Symbol *> UsedIndexResults;
1446 auto CorrespondingIndexResult =
1447 [&](
const CodeCompletionResult &
SemaResult) ->
const Symbol * {
1449 getSymbolID(SemaResult, Recorder->CCSema->getSourceManager())) {
1450 auto I = IndexResults.find(*SymID);
1451 if (I != IndexResults.end()) {
1452 UsedIndexResults.insert(&*I);
1459 for (
auto &SemaResult : Recorder->Results)
1460 AddToBundles(&SemaResult, CorrespondingIndexResult(SemaResult));
1468 TopN<ScoredBundle, ScoredBundleGreater> Top(
1469 Opts.Limit == 0 ? std::numeric_limits<size_t>::max() : Opts.Limit);
1470 for (
auto &Bundle : Bundles)
1471 addCandidate(Top, std::move(Bundle));
1472 return std::move(Top).items();
1475 llvm::Optional<float> fuzzyScore(
const CompletionCandidate &C) {
1478 if (C.SemaResult && C.SemaResult->Kind == CodeCompletionResult::RK_Macro &&
1479 !C.Name.startswith_lower(Filter->pattern()))
1481 return Filter->match(C.Name);
1485 void addCandidate(TopN<ScoredBundle, ScoredBundleGreater> &Candidates,
1486 CompletionCandidate::Bundle Bundle) {
1488 SymbolRelevanceSignals Relevance;
1489 Relevance.Context = Recorder->CCContext.getKind();
1491 Relevance.FileProximityMatch = FileProximity.getPointer();
1493 Relevance.ScopeProximityMatch = ScopeProximity.getPointer();
1495 Relevance.HadContextType =
true;
1497 auto &First = Bundle.front();
1498 if (
auto FuzzyScore = fuzzyScore(First))
1499 Relevance.NameMatch = *FuzzyScore;
1503 bool FromIndex =
false;
1504 for (
const auto &Candidate : Bundle) {
1505 if (Candidate.IndexResult) {
1506 Quality.merge(*Candidate.IndexResult);
1507 Relevance.merge(*Candidate.IndexResult);
1508 Origin |= Candidate.IndexResult->Origin;
1510 if (!Candidate.IndexResult->Type.empty())
1511 Relevance.HadSymbolType |=
true;
1512 if (PreferredType &&
1513 PreferredType->raw() == Candidate.IndexResult->Type) {
1514 Relevance.TypeMatchesPreferred =
true;
1517 if (Candidate.SemaResult) {
1518 Quality.merge(*Candidate.SemaResult);
1519 Relevance.merge(*Candidate.SemaResult);
1520 if (PreferredType) {
1522 Recorder->CCSema->getASTContext(), *Candidate.SemaResult)) {
1523 Relevance.HadSymbolType |=
true;
1524 if (PreferredType == CompletionType)
1525 Relevance.TypeMatchesPreferred =
true;
1532 CodeCompletion::Scores Scores;
1533 Scores.Quality = Quality.evaluate();
1534 Scores.Relevance = Relevance.evaluate();
1537 Scores.ExcludingName = Relevance.NameMatch
1538 ? Scores.Total / Relevance.NameMatch
1541 dlog(
"CodeComplete: {0} ({1}) = {2}\n{3}{4}\n", First.Name,
1542 llvm::to_string(Origin), Scores.Total, llvm::to_string(Quality),
1543 llvm::to_string(Relevance));
1546 NIndex += FromIndex;
1547 NBoth += bool(Origin & SymbolOrigin::AST) && FromIndex;
1548 if (Candidates.push({std::move(Bundle), Scores}))
1552 CodeCompletion toCodeCompletion(
const CompletionCandidate::Bundle &Bundle) {
1553 llvm::Optional<CodeCompletionBuilder> Builder;
1554 for (
const auto &Item : Bundle) {
1555 CodeCompletionString *SemaCCS =
1556 Item.SemaResult ? Recorder->codeCompletionString(*Item.SemaResult)
1559 Builder.emplace(Recorder->CCSema->getASTContext(), Item, SemaCCS,
1561 Recorder->CCContext.getKind(), Opts);
1563 Builder->add(Item, SemaCCS);
1565 return Builder->build();
1572 clang::CodeCompleteOptions
Result;
1573 Result.IncludeCodePatterns = EnableSnippets && IncludeCodePatterns;
1574 Result.IncludeMacros = IncludeMacros;
1575 Result.IncludeGlobals =
true;
1580 Result.IncludeBriefComments =
false;
1585 Result.LoadExternal = !
Index;
1586 Result.IncludeFixIts = IncludeFixIts;
1591 llvm::Expected<llvm::StringRef>
1595 return llvm::make_error<llvm::StringError>(
1596 "Failed to convert position to offset in content.",
1597 llvm::inconvertibleErrorCode());
1602 int St = *Offset - 1;
1604 auto IsValidIdentifierChar = [](
char c) {
1605 return ((c >=
'a' && c <=
'z') || (c >=
'A' && c <=
'Z') ||
1606 (c >=
'0' && c <=
'9') || (c ==
'_'));
1609 for (; (St >= 0) && IsValidIdentifierChar(Content[St]); --St, ++Len) {
1613 return Content.substr(St, Len);
1619 Position Pos, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
VFS,
1620 std::shared_ptr<PCHContainerOperations>
PCHs,
1622 return CodeCompleteFlow(FileName,
1624 SpecFuzzyFind, Opts)
1629 const tooling::CompileCommand &
Command,
1632 llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
VFS,
1633 std::shared_ptr<PCHContainerOperations>
PCHs,
1636 clang::CodeCompleteOptions Options;
1637 Options.IncludeGlobals =
false;
1638 Options.IncludeMacros =
false;
1639 Options.IncludeCodePatterns =
false;
1640 Options.IncludeBriefComments =
false;
1643 llvm::make_unique<SignatureHelpCollector>(Options, Index, Result),
1651 auto InTopLevelScope = [](
const NamedDecl &ND) {
1652 switch (ND.getDeclContext()->getDeclKind()) {
1653 case Decl::TranslationUnit:
1655 case Decl::LinkageSpec:
1662 if (InTopLevelScope(ND))
1665 if (
const auto *EnumDecl = dyn_cast<clang::EnumDecl>(ND.getDeclContext()))
1666 return InTopLevelScope(*EnumDecl) && !EnumDecl->isScoped();
1673 const auto *InsertInclude = Includes.empty() ? nullptr : &Includes[0];
1674 LSP.
label = ((InsertInclude && InsertInclude->Insertion)
1677 (Opts.
ShowOrigins ?
"[" + llvm::to_string(Origin) +
"]" :
"") +
1681 LSP.
detail = BundleSize > 1 ? llvm::formatv(
"[{0} overloads]", BundleSize)
1685 LSP.
detail +=
"\n" + InsertInclude->Header;
1689 LSP.
textEdit = {CompletionTokenRange, RequiredQualifier +
Name};
1697 for (
const auto &
FixIt : FixIts) {
1713 if (InsertInclude && InsertInclude->Insertion)
1727 <<
" (" << getCompletionKindString(R.
Context) <<
")" std::string insertText
A string that should be inserted to a document when selecting this completion.
std::vector< std::string > AccessibleScopes
bool ShowOrigins
Expose origins of completion items in the label (for debugging).
SignatureHelp signatureHelp(PathRef FileName, const tooling::CompileCommand &Command, const PreambleData *Preamble, llvm::StringRef Contents, Position Pos, llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > VFS, std::shared_ptr< PCHContainerOperations > PCHs, const SymbolIndex *Index)
const tooling::CompileCommand & Command
CodeCompleteResult codeComplete(PathRef FileName, const tooling::CompileCommand &Command, const PreambleData *Preamble, llvm::StringRef Contents, Position Pos, llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > VFS, std::shared_ptr< PCHContainerOperations > PCHs, CodeCompleteOptions Opts, SpeculativeFuzzyFind *SpecFuzzyFind)
SignatureQualitySignals Quality
llvm::json::Value toJSON(const FuzzyFindRequest &Request)
CodeCompletionContext::Kind Context
std::string printQualifiedName(const NamedDecl &ND)
Returns the qualified name of ND.
llvm::Optional< TextEdit > textEdit
An edit which is applied to a document when selecting this completion.
llvm::Optional< SymbolID > getSymbolID(const Decl *D)
Gets the symbol ID for a declaration, if possible.
static llvm::Optional< OpaqueType > fromType(ASTContext &Ctx, QualType Type)
Construct an instance from a clang::QualType.
llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > VFS
CompletionItemKind kind
The kind of this completion item.
bool EnableSnippets
When true, completion items will contain expandable code snippets in completion (e.g.
clang::find_all_symbols::SymbolInfo::SymbolKind SymbolKind
std::string printNamespaceScope(const DeclContext &DC)
Returns the first enclosing namespace scope starting from DC.
std::vector< CodeCompletion > Completions
Interface for symbol indexes that can be used for searching or matching symbols among a set of symbol...
bool IsRangeConsecutive(const Range &Left, const Range &Right)
std::string sortText(float Score, llvm::StringRef Name)
Returns a string that sorts in the same order as (-Score, Tiebreak), for LSP.
llvm::StringRef PathRef
A typedef to represent a ref to file path.
llvm::Optional< std::string > UnresolvedQualifier
std::vector< CodeCompletionResult > Results
std::string sortText
A string that should be used when comparing this item with other items.
std::string getDocComment(const ASTContext &Ctx, const CodeCompletionResult &Result, bool CommentsFromHeaders)
Gets a minimally formatted documentation comment of Result, with comment markers stripped.
Documents should not be synced at all.
llvm::Expected< llvm::StringRef > speculateCompletionFilter(llvm::StringRef Content, Position Pos)
Retrives a speculative code completion filter text before the cursor.
std::string documentation
A human-readable string that represents a doc-comment.
void vlog(const char *Fmt, Ts &&... Vals)
std::vector< TextEdit > additionalTextEdits
An optional array of additional text edits that are applied when selecting this completion.
void elog(const char *Fmt, Ts &&... Vals)
static ClangTidyModuleRegistry::Add< AbseilModule > X("abseil-module", "Add Abseil checks.")
CompletionItemKind
The kind of a completion entry.
std::string getReturnType(const CodeCompletionString &CCS)
Gets detail to be used as the detail field in an LSP completion item.
std::string detail
A human-readable string with additional information about this item, like type or symbol information...
std::pair< size_t, size_t > offsetToClangLineColumn(llvm::StringRef Code, size_t Offset)
std::vector< SymbolDetails > getSymbolInfo(ParsedAST &AST, Position Pos)
Get info about symbols at Pos.
TextEdit toTextEdit(const FixItHint &FixIt, const SourceManager &M, const LangOptions &L)
bool isIndexedForCodeCompletion(const NamedDecl &ND, ASTContext &ASTCtx)
std::string filterText
A string that should be used when filtering a set of completion items.
llvm::Expected< size_t > positionToOffset(llvm::StringRef Code, Position P, bool AllowColumnsBeyondLineLength)
Turn a [line, column] pair into an offset in Code.
A speculative and asynchronous fuzzy find index request (based on cached request) that can be sent be...
bool deprecated
Indicates if this item is deprecated.
llvm::unique_function< void()> Action
void log(const char *Fmt, Ts &&... Vals)
llvm::Optional< llvm::Expected< tooling::AtomicChanges > > Result
const Symbol * IndexResult
std::string formatDocumentation(const CodeCompletionString &CCS, llvm::StringRef DocComment)
Assembles formatted documentation for a completion result.
clang::CodeCompleteOptions getClangCompleteOpts() const
Returns options that can be passed to clang's completion engine.
std::string SnippetSuffix
Position sourceLocToPosition(const SourceManager &SM, SourceLocation Loc)
Turn a SourceLocation into a [line, column] pair.
float evaluateSymbolAndRelevance(float SymbolQuality, float SymbolRelevance)
Combine symbol quality and relevance into a single score.
std::string getDeclComment(const ASTContext &Ctx, const NamedDecl &Decl)
Similar to getDocComment, but returns the comment for a NamedDecl.
Represents the signature of a callable.
void getSignature(const CodeCompletionString &CCS, std::string *Signature, std::string *Snippet, std::string *RequiredQualifiers)
Formats the signature for an item, as a display string and snippet.
const PreambleData * Preamble
std::unique_ptr< PPCallbacks > collectIncludeStructureCallback(const SourceManager &SM, IncludeStructure *Out)
Returns a PPCallback that visits all inclusions in the main file.
llvm::SmallVector< llvm::StringRef, 1 > RankedIncludeHeaders
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
std::string label
The label of this completion item.
CompletionItem render(const CodeCompleteOptions &) const
std::shared_ptr< PCHContainerOperations > PCHs
struct clang::clangd::CodeCompleteOptions::IncludeInsertionIndicator IncludeIndicator
CharSourceRange Range
SourceRange for the file name.
std::pair< llvm::StringRef, llvm::StringRef > splitQualifiedName(llvm::StringRef QName)
From "a::b::c", return {"a::b::", "c"}.
const CodeCompletionResult * SemaResult
static llvm::Expected< std::string > resolve(const URI &U, llvm::StringRef HintPath="")
Resolves the absolute path of U.
static llvm::cl::opt< bool > EnableFunctionArgSnippets("function-arg-placeholders", llvm::cl::desc("When disabled, completions contain only parentheses for " "function calls. When enabled, completions also contain " "placeholders for method parameters."), llvm::cl::init(CodeCompleteOptions().EnableFunctionArgSnippets))
llvm::Optional< FixItHint > FixIt
Indicates if the symbol is deprecated.
static llvm::Expected< std::string > includeSpelling(const URI &U)
Gets the preferred spelling of this file for #include, if there is one, e.g.
static llvm::Expected< URI > parse(llvm::StringRef Uri)
Parse a URI string "<scheme>:[//<authority>/]<path>".
static std::string join(ArrayRef< SpecialMemberFunctionsCheck::SpecialMemberFunctionKind > SMFS, llvm::StringRef AndOr)
IncludeStructure Includes
llvm::raw_ostream & operator<<(llvm::raw_ostream &OS, const CodeCompletion &C)
std::unique_ptr< CompilerInstance > prepareCompilerInstance(std::unique_ptr< clang::CompilerInvocation > CI, const PrecompiledPreamble *Preamble, std::unique_ptr< llvm::MemoryBuffer > Buffer, std::shared_ptr< PCHContainerOperations > PCHs, llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > VFS, DiagnosticConsumer &DiagsClient)
InsertTextFormat insertTextFormat
The format of the insert text.
bool isLiteralInclude(llvm::StringRef Include)
Returns true if Include is literal include like "path" or <path>.
CodeCompletionContext CCContext
#define SPAN_ATTACH(S, Name, Expr)
Attach a key-value pair to a Span event.
llvm::Optional< SymbolID > IDForDoc
static llvm::Optional< OpaqueType > fromCompletionResult(ASTContext &Ctx, const CodeCompletionResult &R)
Create a type from a code completion result.
Range halfOpenToRange(const SourceManager &SM, CharSourceRange R)
const SymbolIndex * Index