2323#include < cxx/ast.h>
2424#include < cxx/control.h>
2525#include < cxx/gcc_linux_toolchain.h>
26+ #include < cxx/lsp/enums.h>
2627#include < cxx/lsp/types.h>
2728#include < cxx/macos_toolchain.h>
29+ #include < cxx/name_printer.h>
2830#include < cxx/preprocessor.h>
2931#include < cxx/private/path.h>
3032#include < cxx/scope.h>
3133#include < cxx/symbol_printer.h>
3234#include < cxx/symbols.h>
3335#include < cxx/translation_unit.h>
36+ #include < cxx/type_printer.h>
37+ #include < cxx/types.h>
3438#include < cxx/wasm32_wasi_toolchain.h>
3539#include < cxx/windows_toolchain.h>
3640
3741#ifndef CXX_NO_THREADS
3842#include < atomic>
3943#endif
4044
45+ #include < format>
46+ #include < iostream>
47+
4148namespace cxx ::lsp {
4249
4350namespace {
@@ -74,6 +81,7 @@ struct CxxDocument::Private {
7481 Diagnostics diagnosticsClient;
7582 TranslationUnit unit{&diagnosticsClient};
7683 std::shared_ptr<Toolchain> toolchain;
84+ Vector<CompletionItem> completionItems;
7785
7886#ifndef CXX_NO_THREADS
7987 std::atomic<bool > cancelled{false };
@@ -202,10 +210,20 @@ void CxxDocument::cancel() {
202210
203211auto CxxDocument::fileName () const -> const std::string& { return d->fileName ; }
204212
205- void CxxDocument::requestCodeCompletion (std::uint32_t line,
206- std::uint32_t column) {
213+ void CxxDocument::codeCompletionAt (std::string source, std::uint32_t line,
214+ std::uint32_t column,
215+ Vector<CompletionItem> completionItems) {
216+ std::swap (d->completionItems , completionItems);
217+
207218 auto & unit = d->unit ;
219+
220+ (void )unit.blockErrors (true );
221+
208222 unit.preprocessor ()->requestCodeCompletionAt (line, column);
223+
224+ parse (std::move (source));
225+
226+ std::swap (d->completionItems , completionItems);
209227}
210228
211229void CxxDocument::parse (std::string source) {
@@ -227,13 +245,37 @@ void CxxDocument::parse(std::string source) {
227245
228246 unit.endPreprocessing ();
229247
248+ auto stopParsingPredicate = [this ] { return isCancelled (); };
249+
250+ auto complete = [this ](const CodeCompletionContext& context) {
251+ if (auto memberCompletionContext =
252+ std::get_if<MemberCompletionContext>(&context)) {
253+ // simple member completion
254+ auto objectType = memberCompletionContext->objectType ;
255+
256+ if (auto pointerType = type_cast<PointerType>(objectType)) {
257+ objectType = type_cast<ClassType>(pointerType->elementType ());
258+ }
259+
260+ if (auto classType = type_cast<ClassType>(objectType)) {
261+ auto classSymbol = classType->symbol ();
262+ for (auto member : classSymbol->members ()) {
263+ if (!member->name ()) continue ;
264+ auto item = d->completionItems .emplace_back ();
265+ item.label (to_string (member->name ()));
266+ }
267+ }
268+ }
269+ };
270+
230271 unit.parse (ParserConfiguration{
231272 .checkTypes = cli.opt_fcheck ,
232273 .fuzzyTemplateResolution = true ,
233274 .staticAssert = cli.opt_fstatic_assert || cli.opt_fcheck ,
234275 .reflect = !cli.opt_fno_reflect ,
235276 .templates = cli.opt_ftemplates ,
236- .stopParsingPredicate = [this ] { return isCancelled (); },
277+ .stopParsingPredicate = stopParsingPredicate,
278+ .complete = complete,
237279 });
238280}
239281
0 commit comments