23
23
#include " clang/Frontend/FrontendActions.h"
24
24
#include " clang/Sema/CodeCompleteConsumer.h"
25
25
#include " clang/Sema/Sema.h"
26
+ #include " llvm/Support/Format.h"
26
27
#include < queue>
27
28
28
29
namespace clang {
@@ -558,10 +559,27 @@ bool invokeCodeComplete(const Context &Ctx,
558
559
}
559
560
560
561
CompletionItem indexCompletionItem (const Symbol &Sym, llvm::StringRef Filter,
561
- const SpecifiedScope &SSInfo) {
562
+ const SpecifiedScope &SSInfo,
563
+ llvm::StringRef DebuggingLabel = " " ) {
562
564
CompletionItem Item;
563
565
Item.kind = toCompletionItemKind (Sym.SymInfo .Kind );
564
- Item.label = Sym.Name ;
566
+ // Add DebuggingLabel to the completion results if DebuggingLabel is not
567
+ // empty.
568
+ //
569
+ // For symbols from static index, there are prefix "[G]" in the
570
+ // results (which is used for debugging purpose).
571
+ // So completion list will be like:
572
+ // clang::symbol_from_dynamic_index
573
+ // [G]clang::symbol_from_static_index
574
+ //
575
+ // FIXME: Find out a better way to show the index source.
576
+ if (!DebuggingLabel.empty ()) {
577
+ llvm::raw_string_ostream Label (Item.label );
578
+ Label << llvm::format (" [%s]%s" , DebuggingLabel.str ().c_str (),
579
+ Sym.Name .str ().c_str ());
580
+ } else {
581
+ Item.label = Sym.Name ;
582
+ }
565
583
// FIXME(ioeric): support inserting/replacing scope qualifiers.
566
584
567
585
// FIXME(ioeric): support snippets.
@@ -582,16 +600,18 @@ CompletionItem indexCompletionItem(const Symbol &Sym, llvm::StringRef Filter,
582
600
583
601
void completeWithIndex (const Context &Ctx, const SymbolIndex &Index,
584
602
llvm::StringRef Code, const SpecifiedScope &SSInfo,
585
- llvm::StringRef Filter, CompletionList *Items) {
603
+ llvm::StringRef Filter, CompletionList *Items,
604
+ llvm::StringRef DebuggingLabel = " " ) {
586
605
FuzzyFindRequest Req;
587
606
Req.Query = Filter;
588
607
// FIXME(ioeric): add more possible scopes based on using namespaces and
589
608
// containing namespaces.
590
609
StringRef Scope = SSInfo.Resolved .empty () ? SSInfo.Written : SSInfo.Resolved ;
591
610
Req.Scopes = {Scope.trim (' :' ).str ()};
592
611
593
- Items->isIncomplete = !Index.fuzzyFind (Ctx, Req, [&](const Symbol &Sym) {
594
- Items->items .push_back (indexCompletionItem (Sym, Filter, SSInfo));
612
+ Items->isIncomplete |= !Index.fuzzyFind (Ctx, Req, [&](const Symbol &Sym) {
613
+ Items->items .push_back (
614
+ indexCompletionItem (Sym, Filter, SSInfo, DebuggingLabel));
595
615
});
596
616
}
597
617
@@ -644,13 +664,19 @@ CompletionList codeComplete(const Context &Ctx, PathRef FileName,
644
664
invokeCodeComplete (Ctx, std::move (Consumer), Opts.getClangCompleteOpts (),
645
665
FileName, Command, Preamble, Contents, Pos, std::move (VFS),
646
666
std::move (PCHs));
647
- if (Opts.Index && CompletedName.SSInfo ) {
648
- if (!Results.items .empty ())
649
- log (Ctx, " WARNING: Got completion results from sema for completion on "
650
- " qualified ID while symbol index is provided." );
651
- Results.items .clear ();
652
- completeWithIndex (Ctx, *Opts.Index , Contents, *CompletedName.SSInfo ,
653
- CompletedName.Filter , &Results);
667
+
668
+ // Got scope specifier (ns::f^) for code completion from sema, try to query
669
+ // global symbols from indexes.
670
+ if (CompletedName.SSInfo ) {
671
+ // FIXME: figure out a good algorithm to merge symbols from different
672
+ // sources (dynamic index, static index, AST symbols from clang's completion
673
+ // engine).
674
+ if (Opts.Index )
675
+ completeWithIndex (Ctx, *Opts.Index , Contents, *CompletedName.SSInfo ,
676
+ CompletedName.Filter , &Results);
677
+ if (Opts.StaticIndex )
678
+ completeWithIndex (Ctx, *Opts.StaticIndex , Contents, *CompletedName.SSInfo ,
679
+ CompletedName.Filter , &Results, /* DebuggingLabel=*/ " G" );
654
680
}
655
681
return Results;
656
682
}
0 commit comments