|
10 | 10 | #include "clang/Basic/Version.h"
|
11 | 11 | #include "clang/Config/config.h"
|
12 | 12 |
|
| 13 | +#if CLANG_VERSION_MAJOR >= 18 |
| 14 | +#include "clang/Interpreter/CodeCompletion.h" |
| 15 | +#endif |
| 16 | + |
13 | 17 | #include "llvm/ADT/SmallString.h"
|
14 | 18 | #include "llvm/ADT/StringRef.h"
|
15 | 19 | #include "llvm/ADT/Twine.h"
|
|
28 | 32 |
|
29 | 33 | #include "cling/Utils/AST.h"
|
30 | 34 |
|
| 35 | +#include <regex> |
| 36 | + |
31 | 37 | namespace Cpp {
|
32 | 38 | namespace Cpp_utils = cling::utils;
|
33 | 39 | }
|
@@ -69,6 +75,30 @@ getSymbolAddress(const cling::Interpreter& I, llvm::StringRef IRName) {
|
69 | 75 | Names.push_back(Jit.getExecutionSession().intern(IRName));
|
70 | 76 | return llvm::make_error<llvm::orc::SymbolsNotFound>(Names);
|
71 | 77 | }
|
| 78 | + |
| 79 | +inline void codeComplete(std::vector<std::string>& Results, |
| 80 | + const cling::Interpreter& I, const char* code, |
| 81 | + unsigned complete_line = 1U, |
| 82 | + unsigned complete_column = 1U) { |
| 83 | + std::vector<std::string> results; |
| 84 | + size_t column = complete_column; |
| 85 | + I.codeComplete(code, column, results); |
| 86 | + |
| 87 | + // append cleaned results |
| 88 | + for (auto& r : results) { |
| 89 | + // remove the definition at the beginning (for example [#int#]) |
| 90 | + r = std::regex_replace(r, std::regex("\\[\\#.*\\#\\]"), ""); |
| 91 | + // remove the variable name in <#type name#> |
| 92 | + r = std::regex_replace(r, std::regex("(\\ |\\*)+(\\w+)(\\#\\>)"), "$1$3"); |
| 93 | + // remove unnecessary space at the end of <#type #> |
| 94 | + r = std::regex_replace(r, std::regex("\\ *(\\#\\>)"), "$1"); |
| 95 | + // remove <# #> to keep only the type |
| 96 | + r = std::regex_replace(r, std::regex("\\<\\#([^#>]*)\\#\\>"), "$1"); |
| 97 | + if (r.find(code) == 0) |
| 98 | + Results.push_back(r); |
| 99 | + } |
| 100 | +} |
| 101 | + |
72 | 102 | } // namespace compat
|
73 | 103 |
|
74 | 104 | #endif // USE_CLING
|
@@ -184,6 +214,7 @@ inline void maybeMangleDeclName(const clang::GlobalDecl& GD,
|
184 | 214 | // Clang 14 - Add new Interpreter methods: getExecutionEngine,
|
185 | 215 | // getSymbolAddress, getSymbolAddressFromLinkerName
|
186 | 216 | // Clang 15 - Add new Interpreter methods: Undo
|
| 217 | +// Clang 18 - Add new Interpreter methods: CodeComplete |
187 | 218 |
|
188 | 219 | inline llvm::orc::LLJIT* getExecutionEngine(clang::Interpreter& I) {
|
189 | 220 | #if CLANG_VERSION_MAJOR >= 14
|
@@ -247,6 +278,39 @@ inline llvm::Error Undo(clang::Interpreter& I, unsigned N = 1) {
|
247 | 278 | #endif
|
248 | 279 | }
|
249 | 280 |
|
| 281 | +inline void codeComplete(std::vector<std::string>& Results, |
| 282 | + clang::Interpreter& I, const char* code, |
| 283 | + unsigned complete_line = 1U, |
| 284 | + unsigned complete_column = 1U) { |
| 285 | +#if CLANG_VERSION_MAJOR >= 18 |
| 286 | + // FIXME: We should match the invocation arguments of the main interpreter. |
| 287 | + // That can affect the returned completion results. |
| 288 | + auto CB = clang::IncrementalCompilerBuilder(); |
| 289 | + auto CI = CB.CreateCpp(); |
| 290 | + if (auto Err = CI.takeError()) { |
| 291 | + llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "error: "); |
| 292 | + return; |
| 293 | + } |
| 294 | + auto Interp = clang::Interpreter::create(std::move(*CI)); |
| 295 | + if (auto Err = Interp.takeError()) { |
| 296 | + llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "error: "); |
| 297 | + return; |
| 298 | + } |
| 299 | + |
| 300 | + std::vector<std::string> results; |
| 301 | + std::vector<std::string> Comps; |
| 302 | + clang::CompilerInstance* MainCI = (*Interp)->getCompilerInstance(); |
| 303 | + auto CC = clang::ReplCodeCompleter(); |
| 304 | + CC.codeComplete(MainCI, code, complete_line, complete_column, |
| 305 | + I.getCompilerInstance(), results); |
| 306 | + for (llvm::StringRef r : results) |
| 307 | + if (r.find(CC.Prefix) == 0) |
| 308 | + Results.push_back(r.str()); |
| 309 | +#else |
| 310 | + assert(false && "CodeCompletion API only available in Clang >= 18."); |
| 311 | +#endif |
| 312 | +} |
| 313 | + |
250 | 314 | } // namespace compat
|
251 | 315 |
|
252 | 316 | #include "CppInterOpInterpreter.h"
|
|
0 commit comments