xref: /freebsd-src/contrib/llvm-project/clang/lib/Interpreter/CodeCompletion.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
15f757f3fSDimitry Andric //===------ CodeCompletion.cpp - Code Completion for ClangRepl -------===//
25f757f3fSDimitry Andric //
35f757f3fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f757f3fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f757f3fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65f757f3fSDimitry Andric //
75f757f3fSDimitry Andric //===----------------------------------------------------------------------===//
85f757f3fSDimitry Andric //
95f757f3fSDimitry Andric // This file implements the classes which performs code completion at the REPL.
105f757f3fSDimitry Andric //
115f757f3fSDimitry Andric //===----------------------------------------------------------------------===//
125f757f3fSDimitry Andric 
135f757f3fSDimitry Andric #include "clang/Interpreter/CodeCompletion.h"
145f757f3fSDimitry Andric #include "clang/AST/ASTImporter.h"
15cb14a3feSDimitry Andric #include "clang/AST/DeclLookups.h"
165f757f3fSDimitry Andric #include "clang/AST/DeclarationName.h"
175f757f3fSDimitry Andric #include "clang/AST/ExternalASTSource.h"
185f757f3fSDimitry Andric #include "clang/Basic/IdentifierTable.h"
195f757f3fSDimitry Andric #include "clang/Frontend/ASTUnit.h"
205f757f3fSDimitry Andric #include "clang/Frontend/CompilerInstance.h"
215f757f3fSDimitry Andric #include "clang/Frontend/FrontendActions.h"
225f757f3fSDimitry Andric #include "clang/Interpreter/Interpreter.h"
235f757f3fSDimitry Andric #include "clang/Lex/PreprocessorOptions.h"
245f757f3fSDimitry Andric #include "clang/Sema/CodeCompleteConsumer.h"
255f757f3fSDimitry Andric #include "clang/Sema/CodeCompleteOptions.h"
265f757f3fSDimitry Andric #include "clang/Sema/Sema.h"
27cb14a3feSDimitry Andric #include "llvm/Support/Debug.h"
28cb14a3feSDimitry Andric #define DEBUG_TYPE "REPLCC"
295f757f3fSDimitry Andric 
305f757f3fSDimitry Andric namespace clang {
315f757f3fSDimitry Andric 
325f757f3fSDimitry Andric const std::string CodeCompletionFileName = "input_line_[Completion]";
335f757f3fSDimitry Andric 
345f757f3fSDimitry Andric clang::CodeCompleteOptions getClangCompleteOpts() {
355f757f3fSDimitry Andric   clang::CodeCompleteOptions Opts;
365f757f3fSDimitry Andric   Opts.IncludeCodePatterns = true;
375f757f3fSDimitry Andric   Opts.IncludeMacros = true;
385f757f3fSDimitry Andric   Opts.IncludeGlobals = true;
395f757f3fSDimitry Andric   Opts.IncludeBriefComments = true;
405f757f3fSDimitry Andric   return Opts;
415f757f3fSDimitry Andric }
425f757f3fSDimitry Andric 
435f757f3fSDimitry Andric class ReplCompletionConsumer : public CodeCompleteConsumer {
445f757f3fSDimitry Andric public:
45cb14a3feSDimitry Andric   ReplCompletionConsumer(std::vector<std::string> &Results,
46cb14a3feSDimitry Andric                          ReplCodeCompleter &CC)
475f757f3fSDimitry Andric       : CodeCompleteConsumer(getClangCompleteOpts()),
485f757f3fSDimitry Andric         CCAllocator(std::make_shared<GlobalCodeCompletionAllocator>()),
49cb14a3feSDimitry Andric         CCTUInfo(CCAllocator), Results(Results), CC(CC) {}
505f757f3fSDimitry Andric 
51cb14a3feSDimitry Andric   // The entry of handling code completion. When the function is called, we
52cb14a3feSDimitry Andric   // create a `Context`-based handler (see classes defined below) to handle each
53cb14a3feSDimitry Andric   // completion result.
545f757f3fSDimitry Andric   void ProcessCodeCompleteResults(class Sema &S, CodeCompletionContext Context,
555f757f3fSDimitry Andric                                   CodeCompletionResult *InResults,
565f757f3fSDimitry Andric                                   unsigned NumResults) final;
575f757f3fSDimitry Andric 
585f757f3fSDimitry Andric   CodeCompletionAllocator &getAllocator() override { return *CCAllocator; }
595f757f3fSDimitry Andric 
605f757f3fSDimitry Andric   CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; }
615f757f3fSDimitry Andric 
625f757f3fSDimitry Andric private:
635f757f3fSDimitry Andric   std::shared_ptr<GlobalCodeCompletionAllocator> CCAllocator;
645f757f3fSDimitry Andric   CodeCompletionTUInfo CCTUInfo;
655f757f3fSDimitry Andric   std::vector<std::string> &Results;
66cb14a3feSDimitry Andric   ReplCodeCompleter &CC;
67cb14a3feSDimitry Andric };
68cb14a3feSDimitry Andric 
69cb14a3feSDimitry Andric /// The class CompletionContextHandler contains four interfaces, each of
70cb14a3feSDimitry Andric /// which handles one type of completion result.
71cb14a3feSDimitry Andric /// Its derived classes are used to create concrete handlers based on
72cb14a3feSDimitry Andric /// \c CodeCompletionContext.
73cb14a3feSDimitry Andric class CompletionContextHandler {
74cb14a3feSDimitry Andric protected:
75cb14a3feSDimitry Andric   CodeCompletionContext CCC;
76cb14a3feSDimitry Andric   std::vector<std::string> &Results;
77cb14a3feSDimitry Andric 
78cb14a3feSDimitry Andric private:
79cb14a3feSDimitry Andric   Sema &S;
80cb14a3feSDimitry Andric 
81cb14a3feSDimitry Andric public:
82cb14a3feSDimitry Andric   CompletionContextHandler(Sema &S, CodeCompletionContext CCC,
83cb14a3feSDimitry Andric                            std::vector<std::string> &Results)
84cb14a3feSDimitry Andric       : CCC(CCC), Results(Results), S(S) {}
85cb14a3feSDimitry Andric 
86cb14a3feSDimitry Andric   virtual ~CompletionContextHandler() = default;
87cb14a3feSDimitry Andric   /// Converts a Declaration completion result to a completion string, and then
88cb14a3feSDimitry Andric   /// stores it in Results.
89cb14a3feSDimitry Andric   virtual void handleDeclaration(const CodeCompletionResult &Result) {
90cb14a3feSDimitry Andric     auto PreferredType = CCC.getPreferredType();
91cb14a3feSDimitry Andric     if (PreferredType.isNull()) {
92cb14a3feSDimitry Andric       Results.push_back(Result.Declaration->getName().str());
93cb14a3feSDimitry Andric       return;
94cb14a3feSDimitry Andric     }
95cb14a3feSDimitry Andric 
96cb14a3feSDimitry Andric     if (auto *VD = dyn_cast<VarDecl>(Result.Declaration)) {
97cb14a3feSDimitry Andric       auto ArgumentType = VD->getType();
98cb14a3feSDimitry Andric       if (PreferredType->isReferenceType()) {
99cb14a3feSDimitry Andric         QualType RT = PreferredType->castAs<ReferenceType>()->getPointeeType();
100cb14a3feSDimitry Andric         Sema::ReferenceConversions RefConv;
101cb14a3feSDimitry Andric         Sema::ReferenceCompareResult RefRelationship =
102cb14a3feSDimitry Andric             S.CompareReferenceRelationship(SourceLocation(), RT, ArgumentType,
103cb14a3feSDimitry Andric                                            &RefConv);
104cb14a3feSDimitry Andric         switch (RefRelationship) {
105cb14a3feSDimitry Andric         case Sema::Ref_Compatible:
106cb14a3feSDimitry Andric         case Sema::Ref_Related:
107cb14a3feSDimitry Andric           Results.push_back(VD->getName().str());
108cb14a3feSDimitry Andric           break;
109cb14a3feSDimitry Andric         case Sema::Ref_Incompatible:
110cb14a3feSDimitry Andric           break;
111cb14a3feSDimitry Andric         }
112cb14a3feSDimitry Andric       } else if (S.Context.hasSameType(ArgumentType, PreferredType)) {
113cb14a3feSDimitry Andric         Results.push_back(VD->getName().str());
114cb14a3feSDimitry Andric       }
115cb14a3feSDimitry Andric     }
116cb14a3feSDimitry Andric   }
117cb14a3feSDimitry Andric 
118cb14a3feSDimitry Andric   /// Converts a Keyword completion result to a completion string, and then
119cb14a3feSDimitry Andric   /// stores it in Results.
120cb14a3feSDimitry Andric   virtual void handleKeyword(const CodeCompletionResult &Result) {
121cb14a3feSDimitry Andric     auto Prefix = S.getPreprocessor().getCodeCompletionFilter();
122cb14a3feSDimitry Andric     // Add keyword to the completion results only if we are in a type-aware
123cb14a3feSDimitry Andric     // situation.
124cb14a3feSDimitry Andric     if (!CCC.getBaseType().isNull() || !CCC.getPreferredType().isNull())
125cb14a3feSDimitry Andric       return;
126cb14a3feSDimitry Andric     if (StringRef(Result.Keyword).starts_with(Prefix))
127cb14a3feSDimitry Andric       Results.push_back(Result.Keyword);
128cb14a3feSDimitry Andric   }
129cb14a3feSDimitry Andric 
130cb14a3feSDimitry Andric   /// Converts a Pattern completion result to a completion string, and then
131cb14a3feSDimitry Andric   /// stores it in Results.
132cb14a3feSDimitry Andric   virtual void handlePattern(const CodeCompletionResult &Result) {}
133cb14a3feSDimitry Andric 
134cb14a3feSDimitry Andric   /// Converts a Macro completion result to a completion string, and then stores
135cb14a3feSDimitry Andric   /// it in Results.
136cb14a3feSDimitry Andric   virtual void handleMacro(const CodeCompletionResult &Result) {}
137cb14a3feSDimitry Andric };
138cb14a3feSDimitry Andric 
139cb14a3feSDimitry Andric class DotMemberAccessHandler : public CompletionContextHandler {
140cb14a3feSDimitry Andric public:
141cb14a3feSDimitry Andric   DotMemberAccessHandler(Sema &S, CodeCompletionContext CCC,
142cb14a3feSDimitry Andric                          std::vector<std::string> &Results)
143cb14a3feSDimitry Andric       : CompletionContextHandler(S, CCC, Results) {}
144cb14a3feSDimitry Andric   void handleDeclaration(const CodeCompletionResult &Result) override {
145cb14a3feSDimitry Andric     auto *ID = Result.Declaration->getIdentifier();
146cb14a3feSDimitry Andric     if (!ID)
147cb14a3feSDimitry Andric       return;
148cb14a3feSDimitry Andric     if (!isa<CXXMethodDecl>(Result.Declaration))
149cb14a3feSDimitry Andric       return;
150cb14a3feSDimitry Andric     const auto *Fun = cast<CXXMethodDecl>(Result.Declaration);
151cb14a3feSDimitry Andric     if (Fun->getParent()->getCanonicalDecl() ==
152cb14a3feSDimitry Andric         CCC.getBaseType()->getAsCXXRecordDecl()->getCanonicalDecl()) {
153cb14a3feSDimitry Andric       LLVM_DEBUG(llvm::dbgs() << "[In HandleCodeCompleteDOT] Name : "
154cb14a3feSDimitry Andric                               << ID->getName() << "\n");
155cb14a3feSDimitry Andric       Results.push_back(ID->getName().str());
156cb14a3feSDimitry Andric     }
157cb14a3feSDimitry Andric   }
158cb14a3feSDimitry Andric 
159cb14a3feSDimitry Andric   void handleKeyword(const CodeCompletionResult &Result) override {}
1605f757f3fSDimitry Andric };
1615f757f3fSDimitry Andric 
1625f757f3fSDimitry Andric void ReplCompletionConsumer::ProcessCodeCompleteResults(
1635f757f3fSDimitry Andric     class Sema &S, CodeCompletionContext Context,
1645f757f3fSDimitry Andric     CodeCompletionResult *InResults, unsigned NumResults) {
165cb14a3feSDimitry Andric 
166cb14a3feSDimitry Andric   auto Prefix = S.getPreprocessor().getCodeCompletionFilter();
167cb14a3feSDimitry Andric   CC.Prefix = Prefix;
168cb14a3feSDimitry Andric 
169cb14a3feSDimitry Andric   std::unique_ptr<CompletionContextHandler> CCH;
170cb14a3feSDimitry Andric 
171cb14a3feSDimitry Andric   // initialize fine-grained code completion handler based on the code
172cb14a3feSDimitry Andric   // completion context.
173cb14a3feSDimitry Andric   switch (Context.getKind()) {
174cb14a3feSDimitry Andric   case CodeCompletionContext::CCC_DotMemberAccess:
175cb14a3feSDimitry Andric     CCH.reset(new DotMemberAccessHandler(S, Context, this->Results));
176cb14a3feSDimitry Andric     break;
177cb14a3feSDimitry Andric   default:
178cb14a3feSDimitry Andric     CCH.reset(new CompletionContextHandler(S, Context, this->Results));
179cb14a3feSDimitry Andric   };
180cb14a3feSDimitry Andric 
181cb14a3feSDimitry Andric   for (unsigned I = 0; I < NumResults; I++) {
1825f757f3fSDimitry Andric     auto &Result = InResults[I];
1835f757f3fSDimitry Andric     switch (Result.Kind) {
1845f757f3fSDimitry Andric     case CodeCompletionResult::RK_Declaration:
185cb14a3feSDimitry Andric       if (Result.Hidden) {
186cb14a3feSDimitry Andric         break;
1875f757f3fSDimitry Andric       }
188cb14a3feSDimitry Andric       if (!Result.Declaration->getDeclName().isIdentifier() ||
189cb14a3feSDimitry Andric           !Result.Declaration->getName().starts_with(Prefix)) {
190cb14a3feSDimitry Andric         break;
191cb14a3feSDimitry Andric       }
192cb14a3feSDimitry Andric       CCH->handleDeclaration(Result);
1935f757f3fSDimitry Andric       break;
1945f757f3fSDimitry Andric     case CodeCompletionResult::RK_Keyword:
195cb14a3feSDimitry Andric       CCH->handleKeyword(Result);
1965f757f3fSDimitry Andric       break;
197cb14a3feSDimitry Andric     case CodeCompletionResult::RK_Macro:
198cb14a3feSDimitry Andric       CCH->handleMacro(Result);
199cb14a3feSDimitry Andric       break;
200cb14a3feSDimitry Andric     case CodeCompletionResult::RK_Pattern:
201cb14a3feSDimitry Andric       CCH->handlePattern(Result);
2025f757f3fSDimitry Andric       break;
2035f757f3fSDimitry Andric     }
2045f757f3fSDimitry Andric   }
205cb14a3feSDimitry Andric 
206cb14a3feSDimitry Andric   std::sort(Results.begin(), Results.end());
2075f757f3fSDimitry Andric }
2085f757f3fSDimitry Andric 
2095f757f3fSDimitry Andric class IncrementalSyntaxOnlyAction : public SyntaxOnlyAction {
2105f757f3fSDimitry Andric   const CompilerInstance *ParentCI;
2115f757f3fSDimitry Andric 
2125f757f3fSDimitry Andric public:
2135f757f3fSDimitry Andric   IncrementalSyntaxOnlyAction(const CompilerInstance *ParentCI)
2145f757f3fSDimitry Andric       : ParentCI(ParentCI) {}
2155f757f3fSDimitry Andric 
2165f757f3fSDimitry Andric protected:
2175f757f3fSDimitry Andric   void ExecuteAction() override;
2185f757f3fSDimitry Andric };
2195f757f3fSDimitry Andric 
2205f757f3fSDimitry Andric class ExternalSource : public clang::ExternalASTSource {
2215f757f3fSDimitry Andric   TranslationUnitDecl *ChildTUDeclCtxt;
2225f757f3fSDimitry Andric   ASTContext &ParentASTCtxt;
2235f757f3fSDimitry Andric   TranslationUnitDecl *ParentTUDeclCtxt;
2245f757f3fSDimitry Andric 
2255f757f3fSDimitry Andric   std::unique_ptr<ASTImporter> Importer;
2265f757f3fSDimitry Andric 
2275f757f3fSDimitry Andric public:
2285f757f3fSDimitry Andric   ExternalSource(ASTContext &ChildASTCtxt, FileManager &ChildFM,
2295f757f3fSDimitry Andric                  ASTContext &ParentASTCtxt, FileManager &ParentFM);
2305f757f3fSDimitry Andric   bool FindExternalVisibleDeclsByName(const DeclContext *DC,
2315f757f3fSDimitry Andric                                       DeclarationName Name) override;
2325f757f3fSDimitry Andric   void
2335f757f3fSDimitry Andric   completeVisibleDeclsMap(const clang::DeclContext *childDeclContext) override;
2345f757f3fSDimitry Andric };
2355f757f3fSDimitry Andric 
2365f757f3fSDimitry Andric // This method is intended to set up `ExternalASTSource` to the running
2375f757f3fSDimitry Andric // compiler instance before the super `ExecuteAction` triggers parsing
2385f757f3fSDimitry Andric void IncrementalSyntaxOnlyAction::ExecuteAction() {
2395f757f3fSDimitry Andric   CompilerInstance &CI = getCompilerInstance();
2405f757f3fSDimitry Andric   ExternalSource *myExternalSource =
2415f757f3fSDimitry Andric       new ExternalSource(CI.getASTContext(), CI.getFileManager(),
2425f757f3fSDimitry Andric                          ParentCI->getASTContext(), ParentCI->getFileManager());
2435f757f3fSDimitry Andric   llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> astContextExternalSource(
2445f757f3fSDimitry Andric       myExternalSource);
2455f757f3fSDimitry Andric   CI.getASTContext().setExternalSource(astContextExternalSource);
2465f757f3fSDimitry Andric   CI.getASTContext().getTranslationUnitDecl()->setHasExternalVisibleStorage(
2475f757f3fSDimitry Andric       true);
2485f757f3fSDimitry Andric 
249cb14a3feSDimitry Andric   // Load all external decls into current context. Under the hood, it calls
250cb14a3feSDimitry Andric   // ExternalSource::completeVisibleDeclsMap, which make all decls on the redecl
251cb14a3feSDimitry Andric   // chain visible.
252cb14a3feSDimitry Andric   //
253cb14a3feSDimitry Andric   // This is crucial to code completion on dot members, since a bound variable
254cb14a3feSDimitry Andric   // before "." would be otherwise treated out-of-scope.
255cb14a3feSDimitry Andric   //
256cb14a3feSDimitry Andric   // clang-repl> Foo f1;
257cb14a3feSDimitry Andric   // clang-repl> f1.<tab>
258cb14a3feSDimitry Andric   CI.getASTContext().getTranslationUnitDecl()->lookups();
2595f757f3fSDimitry Andric   SyntaxOnlyAction::ExecuteAction();
2605f757f3fSDimitry Andric }
2615f757f3fSDimitry Andric 
2625f757f3fSDimitry Andric ExternalSource::ExternalSource(ASTContext &ChildASTCtxt, FileManager &ChildFM,
2635f757f3fSDimitry Andric                                ASTContext &ParentASTCtxt, FileManager &ParentFM)
2645f757f3fSDimitry Andric     : ChildTUDeclCtxt(ChildASTCtxt.getTranslationUnitDecl()),
2655f757f3fSDimitry Andric       ParentASTCtxt(ParentASTCtxt),
2665f757f3fSDimitry Andric       ParentTUDeclCtxt(ParentASTCtxt.getTranslationUnitDecl()) {
2675f757f3fSDimitry Andric   ASTImporter *importer =
2685f757f3fSDimitry Andric       new ASTImporter(ChildASTCtxt, ChildFM, ParentASTCtxt, ParentFM,
2695f757f3fSDimitry Andric                       /*MinimalImport : ON*/ true);
2705f757f3fSDimitry Andric   Importer.reset(importer);
2715f757f3fSDimitry Andric }
2725f757f3fSDimitry Andric 
2735f757f3fSDimitry Andric bool ExternalSource::FindExternalVisibleDeclsByName(const DeclContext *DC,
2745f757f3fSDimitry Andric                                                     DeclarationName Name) {
275cb14a3feSDimitry Andric 
2765f757f3fSDimitry Andric   IdentifierTable &ParentIdTable = ParentASTCtxt.Idents;
2775f757f3fSDimitry Andric 
2785f757f3fSDimitry Andric   auto ParentDeclName =
2795f757f3fSDimitry Andric       DeclarationName(&(ParentIdTable.get(Name.getAsString())));
2805f757f3fSDimitry Andric 
2815f757f3fSDimitry Andric   DeclContext::lookup_result lookup_result =
2825f757f3fSDimitry Andric       ParentTUDeclCtxt->lookup(ParentDeclName);
2835f757f3fSDimitry Andric 
2845f757f3fSDimitry Andric   if (!lookup_result.empty()) {
2855f757f3fSDimitry Andric     return true;
2865f757f3fSDimitry Andric   }
2875f757f3fSDimitry Andric   return false;
2885f757f3fSDimitry Andric }
2895f757f3fSDimitry Andric 
2905f757f3fSDimitry Andric void ExternalSource::completeVisibleDeclsMap(
2915f757f3fSDimitry Andric     const DeclContext *ChildDeclContext) {
2925f757f3fSDimitry Andric   assert(ChildDeclContext && ChildDeclContext == ChildTUDeclCtxt &&
2935f757f3fSDimitry Andric          "No child decl context!");
2945f757f3fSDimitry Andric 
2955f757f3fSDimitry Andric   if (!ChildDeclContext->hasExternalVisibleStorage())
2965f757f3fSDimitry Andric     return;
2975f757f3fSDimitry Andric 
2985f757f3fSDimitry Andric   for (auto *DeclCtxt = ParentTUDeclCtxt; DeclCtxt != nullptr;
2995f757f3fSDimitry Andric        DeclCtxt = DeclCtxt->getPreviousDecl()) {
3005f757f3fSDimitry Andric     for (auto &IDeclContext : DeclCtxt->decls()) {
301cb14a3feSDimitry Andric       if (!llvm::isa<NamedDecl>(IDeclContext))
302cb14a3feSDimitry Andric         continue;
303cb14a3feSDimitry Andric 
304cb14a3feSDimitry Andric       NamedDecl *Decl = llvm::cast<NamedDecl>(IDeclContext);
305cb14a3feSDimitry Andric 
306cb14a3feSDimitry Andric       auto DeclOrErr = Importer->Import(Decl);
307cb14a3feSDimitry Andric       if (!DeclOrErr) {
308cb14a3feSDimitry Andric         // if an error happens, it usually means the decl has already been
309cb14a3feSDimitry Andric         // imported or the decl is a result of a failed import.  But in our
310cb14a3feSDimitry Andric         // case, every import is fresh each time code completion is
311cb14a3feSDimitry Andric         // triggered. So Import usually doesn't fail. If it does, it just means
312cb14a3feSDimitry Andric         // the related decl can't be used in code completion and we can safely
313cb14a3feSDimitry Andric         // drop it.
314cb14a3feSDimitry Andric         llvm::consumeError(DeclOrErr.takeError());
315cb14a3feSDimitry Andric         continue;
316cb14a3feSDimitry Andric       }
317cb14a3feSDimitry Andric 
318cb14a3feSDimitry Andric       if (!llvm::isa<NamedDecl>(*DeclOrErr))
319cb14a3feSDimitry Andric         continue;
320cb14a3feSDimitry Andric 
321cb14a3feSDimitry Andric       NamedDecl *importedNamedDecl = llvm::cast<NamedDecl>(*DeclOrErr);
322cb14a3feSDimitry Andric 
3235f757f3fSDimitry Andric       SetExternalVisibleDeclsForName(ChildDeclContext,
3245f757f3fSDimitry Andric                                      importedNamedDecl->getDeclName(),
3255f757f3fSDimitry Andric                                      importedNamedDecl);
326cb14a3feSDimitry Andric 
327cb14a3feSDimitry Andric       if (!llvm::isa<CXXRecordDecl>(importedNamedDecl))
328cb14a3feSDimitry Andric         continue;
329cb14a3feSDimitry Andric 
330cb14a3feSDimitry Andric       auto *Record = llvm::cast<CXXRecordDecl>(importedNamedDecl);
331cb14a3feSDimitry Andric 
332cb14a3feSDimitry Andric       if (auto Err = Importer->ImportDefinition(Decl)) {
333cb14a3feSDimitry Andric         // the same as above
334cb14a3feSDimitry Andric         consumeError(std::move(Err));
335cb14a3feSDimitry Andric         continue;
3365f757f3fSDimitry Andric       }
3375f757f3fSDimitry Andric 
338cb14a3feSDimitry Andric       Record->setHasLoadedFieldsFromExternalStorage(true);
339cb14a3feSDimitry Andric       LLVM_DEBUG(llvm::dbgs()
340cb14a3feSDimitry Andric                  << "\nCXXRecrod : " << Record->getName() << " size(methods): "
341cb14a3feSDimitry Andric                  << std::distance(Record->method_begin(), Record->method_end())
342cb14a3feSDimitry Andric                  << " has def?:  " << Record->hasDefinition()
343cb14a3feSDimitry Andric                  << " # (methods): "
344cb14a3feSDimitry Andric                  << std::distance(Record->getDefinition()->method_begin(),
345cb14a3feSDimitry Andric                                   Record->getDefinition()->method_end())
346cb14a3feSDimitry Andric                  << "\n");
347cb14a3feSDimitry Andric       for (auto *Meth : Record->methods())
348cb14a3feSDimitry Andric         SetExternalVisibleDeclsForName(ChildDeclContext, Meth->getDeclName(),
349cb14a3feSDimitry Andric                                        Meth);
3505f757f3fSDimitry Andric     }
3515f757f3fSDimitry Andric     ChildDeclContext->setHasExternalLexicalStorage(false);
3525f757f3fSDimitry Andric   }
3535f757f3fSDimitry Andric }
3545f757f3fSDimitry Andric 
355cb14a3feSDimitry Andric void ReplCodeCompleter::codeComplete(CompilerInstance *InterpCI,
356cb14a3feSDimitry Andric                                      llvm::StringRef Content, unsigned Line,
357cb14a3feSDimitry Andric                                      unsigned Col,
358cb14a3feSDimitry Andric                                      const CompilerInstance *ParentCI,
3595f757f3fSDimitry Andric                                      std::vector<std::string> &CCResults) {
3605f757f3fSDimitry Andric   auto DiagOpts = DiagnosticOptions();
361cb14a3feSDimitry Andric   auto consumer = ReplCompletionConsumer(CCResults, *this);
3625f757f3fSDimitry Andric 
3635f757f3fSDimitry Andric   auto diag = InterpCI->getDiagnosticsPtr();
3645f757f3fSDimitry Andric   std::unique_ptr<ASTUnit> AU(ASTUnit::LoadFromCompilerInvocationAction(
3655f757f3fSDimitry Andric       InterpCI->getInvocationPtr(), std::make_shared<PCHContainerOperations>(),
3665f757f3fSDimitry Andric       diag));
3675f757f3fSDimitry Andric   llvm::SmallVector<clang::StoredDiagnostic, 8> sd = {};
3685f757f3fSDimitry Andric   llvm::SmallVector<const llvm::MemoryBuffer *, 1> tb = {};
3695f757f3fSDimitry Andric   InterpCI->getFrontendOpts().Inputs[0] = FrontendInputFile(
3705f757f3fSDimitry Andric       CodeCompletionFileName, Language::CXX, InputKind::Source);
371*0fca6ea1SDimitry Andric   auto Act = std::make_unique<IncrementalSyntaxOnlyAction>(ParentCI);
3725f757f3fSDimitry Andric   std::unique_ptr<llvm::MemoryBuffer> MB =
3735f757f3fSDimitry Andric       llvm::MemoryBuffer::getMemBufferCopy(Content, CodeCompletionFileName);
3745f757f3fSDimitry Andric   llvm::SmallVector<ASTUnit::RemappedFile, 4> RemappedFiles;
3755f757f3fSDimitry Andric 
3765f757f3fSDimitry Andric   RemappedFiles.push_back(std::make_pair(CodeCompletionFileName, MB.get()));
3775f757f3fSDimitry Andric   // we don't want the AU destructor to release the memory buffer that MB
3785f757f3fSDimitry Andric   // owns twice, because MB handles its resource on its own.
3795f757f3fSDimitry Andric   AU->setOwnsRemappedFileBuffers(false);
3805f757f3fSDimitry Andric   AU->CodeComplete(CodeCompletionFileName, 1, Col, RemappedFiles, false, false,
3815f757f3fSDimitry Andric                    false, consumer,
3825f757f3fSDimitry Andric                    std::make_shared<clang::PCHContainerOperations>(), *diag,
3835f757f3fSDimitry Andric                    InterpCI->getLangOpts(), InterpCI->getSourceManager(),
3845f757f3fSDimitry Andric                    InterpCI->getFileManager(), sd, tb, std::move(Act));
3855f757f3fSDimitry Andric }
3865f757f3fSDimitry Andric 
3875f757f3fSDimitry Andric } // namespace clang
388