clang 18.0.0git
CodeCompletion.cpp
Go to the documentation of this file.
1//===------ CodeCompletion.cpp - Code Completion for ClangRepl -------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the classes which performs code completion at the REPL.
10//
11//===----------------------------------------------------------------------===//
12
25#include "clang/Sema/Sema.h"
26
27namespace clang {
28
29const std::string CodeCompletionFileName = "input_line_[Completion]";
30
33 Opts.IncludeCodePatterns = true;
34 Opts.IncludeMacros = true;
35 Opts.IncludeGlobals = true;
36 Opts.IncludeBriefComments = true;
37 return Opts;
38}
39
41public:
42 ReplCompletionConsumer(std::vector<std::string> &Results)
44 CCAllocator(std::make_shared<GlobalCodeCompletionAllocator>()),
45 CCTUInfo(CCAllocator), Results(Results){};
46
48 CodeCompletionResult *InResults,
49 unsigned NumResults) final;
50
51 CodeCompletionAllocator &getAllocator() override { return *CCAllocator; }
52
53 CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; }
54
55private:
56 std::shared_ptr<GlobalCodeCompletionAllocator> CCAllocator;
57 CodeCompletionTUInfo CCTUInfo;
58 std::vector<std::string> &Results;
59};
60
62 class Sema &S, CodeCompletionContext Context,
63 CodeCompletionResult *InResults, unsigned NumResults) {
64 for (unsigned I = 0; I < NumResults; ++I) {
65 auto &Result = InResults[I];
66 switch (Result.Kind) {
68 if (auto *ID = Result.Declaration->getIdentifier()) {
69 Results.push_back(ID->getName().str());
70 }
71 break;
73 Results.push_back(Result.Keyword);
74 break;
75 default:
76 break;
77 }
78 }
79}
80
82 const CompilerInstance *ParentCI;
83
84public:
86 : ParentCI(ParentCI) {}
87
88protected:
89 void ExecuteAction() override;
90};
91
93 TranslationUnitDecl *ChildTUDeclCtxt;
94 ASTContext &ParentASTCtxt;
95 TranslationUnitDecl *ParentTUDeclCtxt;
96
97 std::unique_ptr<ASTImporter> Importer;
98
99public:
100 ExternalSource(ASTContext &ChildASTCtxt, FileManager &ChildFM,
101 ASTContext &ParentASTCtxt, FileManager &ParentFM);
103 DeclarationName Name) override;
104 void
105 completeVisibleDeclsMap(const clang::DeclContext *childDeclContext) override;
106};
107
108// This method is intended to set up `ExternalASTSource` to the running
109// compiler instance before the super `ExecuteAction` triggers parsing
112 ExternalSource *myExternalSource =
114 ParentCI->getASTContext(), ParentCI->getFileManager());
116 myExternalSource);
117 CI.getASTContext().setExternalSource(astContextExternalSource);
119 true);
120
122}
123
125 ASTContext &ParentASTCtxt, FileManager &ParentFM)
126 : ChildTUDeclCtxt(ChildASTCtxt.getTranslationUnitDecl()),
127 ParentASTCtxt(ParentASTCtxt),
128 ParentTUDeclCtxt(ParentASTCtxt.getTranslationUnitDecl()) {
129 ASTImporter *importer =
130 new ASTImporter(ChildASTCtxt, ChildFM, ParentASTCtxt, ParentFM,
131 /*MinimalImport : ON*/ true);
132 Importer.reset(importer);
133}
134
136 DeclarationName Name) {
137 IdentifierTable &ParentIdTable = ParentASTCtxt.Idents;
138
139 auto ParentDeclName =
140 DeclarationName(&(ParentIdTable.get(Name.getAsString())));
141
142 DeclContext::lookup_result lookup_result =
143 ParentTUDeclCtxt->lookup(ParentDeclName);
144
145 if (!lookup_result.empty()) {
146 return true;
147 }
148 return false;
149}
150
152 const DeclContext *ChildDeclContext) {
153 assert(ChildDeclContext && ChildDeclContext == ChildTUDeclCtxt &&
154 "No child decl context!");
155
156 if (!ChildDeclContext->hasExternalVisibleStorage())
157 return;
158
159 for (auto *DeclCtxt = ParentTUDeclCtxt; DeclCtxt != nullptr;
160 DeclCtxt = DeclCtxt->getPreviousDecl()) {
161 for (auto &IDeclContext : DeclCtxt->decls()) {
162 if (NamedDecl *Decl = llvm::dyn_cast<NamedDecl>(IDeclContext)) {
163 if (auto DeclOrErr = Importer->Import(Decl)) {
164 if (NamedDecl *importedNamedDecl =
165 llvm::dyn_cast<NamedDecl>(*DeclOrErr)) {
166 SetExternalVisibleDeclsForName(ChildDeclContext,
167 importedNamedDecl->getDeclName(),
168 importedNamedDecl);
169 }
170
171 } else {
172 llvm::consumeError(DeclOrErr.takeError());
173 }
174 }
175 }
176 ChildDeclContext->setHasExternalLexicalStorage(false);
177 }
178}
179
180void codeComplete(CompilerInstance *InterpCI, llvm::StringRef Content,
181 unsigned Line, unsigned Col, const CompilerInstance *ParentCI,
182 std::vector<std::string> &CCResults) {
183 auto DiagOpts = DiagnosticOptions();
184 auto consumer = ReplCompletionConsumer(CCResults);
185
186 auto diag = InterpCI->getDiagnosticsPtr();
187 std::unique_ptr<ASTUnit> AU(ASTUnit::LoadFromCompilerInvocationAction(
188 InterpCI->getInvocationPtr(), std::make_shared<PCHContainerOperations>(),
189 diag));
194 auto Act = std::unique_ptr<IncrementalSyntaxOnlyAction>(
195 new IncrementalSyntaxOnlyAction(ParentCI));
196 std::unique_ptr<llvm::MemoryBuffer> MB =
197 llvm::MemoryBuffer::getMemBufferCopy(Content, CodeCompletionFileName);
199
200 RemappedFiles.push_back(std::make_pair(CodeCompletionFileName, MB.get()));
201 // we don't want the AU destructor to release the memory buffer that MB
202 // owns twice, because MB handles its resource on its own.
203 AU->setOwnsRemappedFileBuffers(false);
204 AU->CodeComplete(CodeCompletionFileName, 1, Col, RemappedFiles, false, false,
205 false, consumer,
206 std::make_shared<clang::PCHContainerOperations>(), *diag,
207 InterpCI->getLangOpts(), InterpCI->getSourceManager(),
208 InterpCI->getFileManager(), sd, tb, std::move(Act));
209}
210
211} // namespace clang
static char ID
Definition: Arena.cpp:183
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:182
TranslationUnitDecl * getTranslationUnitDecl() const
Definition: ASTContext.h:1065
IdentifierTable & Idents
Definition: ASTContext.h:636
void setExternalSource(IntrusiveRefCntPtr< ExternalASTSource > Source)
Attach an external AST source to the AST context.
Definition: ASTContext.cpp:941
Imports selected nodes from one AST context into another context, merging AST nodes where appropriate...
Definition: ASTImporter.h:62
static ASTUnit * LoadFromCompilerInvocationAction(std::shared_ptr< CompilerInvocation > CI, std::shared_ptr< PCHContainerOperations > PCHContainerOps, IntrusiveRefCntPtr< DiagnosticsEngine > Diags, FrontendAction *Action=nullptr, ASTUnit *Unit=nullptr, bool Persistent=true, StringRef ResourceFilesPath=StringRef(), bool OnlyLocalDecls=false, CaptureDiagsKind CaptureDiagnostics=CaptureDiagsKind::None, unsigned PrecompilePreambleAfterNParses=0, bool CacheCodeCompletionResults=false, bool UserFilesAreVolatile=false, std::unique_ptr< ASTUnit > *ErrAST=nullptr)
Create an ASTUnit from a source file, via a CompilerInvocation object, by invoking the optionally pro...
Definition: ASTUnit.cpp:1537
Abstract interface for a consumer of code-completion information.
Options controlling the behavior of code completion.
unsigned IncludeCodePatterns
Show code patterns in code completion results.
unsigned IncludeMacros
Show macros in code completion results.
unsigned IncludeBriefComments
Show brief documentation comments in code completion results.
unsigned IncludeGlobals
Show top-level decls in code completion results.
An allocator used specifically for the purpose of code completion.
The context in which code completion occurred, so that the code-completion consumer can process the r...
Captures a result of code completion.
@ RK_Declaration
Refers to a declaration.
@ RK_Keyword
Refers to a keyword or symbol.
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
FileManager & getFileManager() const
Return the current file manager to the caller.
IntrusiveRefCntPtr< DiagnosticsEngine > getDiagnosticsPtr() const
ASTContext & getASTContext() const
FrontendOptions & getFrontendOpts()
std::shared_ptr< CompilerInvocation > getInvocationPtr()
LangOptions & getLangOpts()
SourceManager & getSourceManager() const
Return the current source manager.
The results of name lookup within a DeclContext.
Definition: DeclBase.h:1368
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1435
void setHasExternalVisibleStorage(bool ES=true) const
State whether this DeclContext has external storage for declarations visible in this context.
Definition: DeclBase.h:2653
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
Definition: DeclBase.cpp:1797
bool hasExternalVisibleStorage() const
Whether this DeclContext has external storage containing additional declarations that are visible in ...
Definition: DeclBase.h:2647
void setHasExternalLexicalStorage(bool ES=true) const
State whether this DeclContext has external storage for declarations lexically in this context.
Definition: DeclBase.h:2641
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:85
Decl * getPreviousDecl()
Retrieve the previous declaration that declares the same entity as this declaration,...
Definition: DeclBase.h:1050
The name of a declaration.
Options for controlling the compiler diagnostics engine.
Abstract interface for external sources of AST nodes.
static DeclContextLookupResult SetExternalVisibleDeclsForName(const DeclContext *DC, DeclarationName Name, ArrayRef< NamedDecl * > Decls)
Definition: DeclBase.cpp:1552
ExternalSource(ASTContext &ChildASTCtxt, FileManager &ChildFM, ASTContext &ParentASTCtxt, FileManager &ParentFM)
void completeVisibleDeclsMap(const clang::DeclContext *childDeclContext) override
Ensures that the table of all visible declarations inside this context is up to date.
bool FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name) override
Find all declarations with the given name in the given context, and add them to the context by callin...
Implements support for file system lookup, file system caching, and directory search management.
Definition: FileManager.h:53
CompilerInstance & getCompilerInstance() const
virtual void ExecuteAction()=0
Callback to run the program action, using the initialized compiler instance.
An input file for the front end.
SmallVector< FrontendInputFile, 0 > Inputs
The input files and their types.
Allocator for a cached set of global code completions.
Implements an efficient mapping from strings to IdentifierInfo nodes.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
IncrementalSyntaxOnlyAction(const CompilerInstance *ParentCI)
void ExecuteAction() override
Implement the ExecuteAction interface by running Sema on the already-initialized AST consumer.
This represents a decl that may have a name.
Definition: Decl.h:248
ReplCompletionConsumer(std::vector< std::string > &Results)
void ProcessCodeCompleteResults(class Sema &S, CodeCompletionContext Context, CodeCompletionResult *InResults, unsigned NumResults) final
Process the finalized code-completion results.
CodeCompletionAllocator & getAllocator() override
Retrieve the allocator that will be used to allocate code completion strings.
CodeCompletionTUInfo & getCodeCompletionTUInfo() override
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:357
The top declaration context.
Definition: Decl.h:83
void codeComplete(CompilerInstance *InterpCI, llvm::StringRef Content, unsigned Line, unsigned Col, const CompilerInstance *ParentCI, std::vector< std::string > &CCResults)
@ Result
The result type of a method or function.
clang::CodeCompleteOptions getClangCompleteOpts()
const std::string CodeCompletionFileName
Definition: Format.h:5226