Skip to content

Commit 9d655fd

Browse files
authored
Merge pull request #9439 from hamishknight/complete-options
[lldb] Pass language options to `ide::isSourceInputComplete`
2 parents c06c587 + a3c6a2e commit 9d655fd

File tree

2 files changed

+97
-80
lines changed

2 files changed

+97
-80
lines changed

lldb/source/Plugins/ExpressionParser/Swift/SwiftREPL.cpp

Lines changed: 93 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -320,9 +320,13 @@ llvm::StringRef SwiftREPL::GetSourceFileBasename() {
320320
bool SwiftREPL::SourceIsComplete(const std::string &source) {
321321
std::unique_ptr<llvm::MemoryBuffer> source_buffer_ap(
322322
llvm::MemoryBuffer::getMemBuffer(source));
323-
swift::ide::SourceCompleteResult result =
324-
swift::ide::isSourceInputComplete(std::move(source_buffer_ap),
325-
swift::SourceFileKind::Main);
323+
auto *swift_ast = getSwiftASTContext();
324+
if (!swift_ast)
325+
return true;
326+
327+
swift::ide::SourceCompleteResult result = swift::ide::isSourceInputComplete(
328+
std::move(source_buffer_ap), swift::SourceFileKind::Main,
329+
swift_ast->GetLanguageOptions());
326330
return result.IsComplete;
327331
}
328332

@@ -355,9 +359,14 @@ lldb::offset_t SwiftREPL::GetDesiredIndentation(const StringList &lines,
355359
std::string source_string(prior_lines.CopyList());
356360
std::unique_ptr<llvm::MemoryBuffer> source_buffer_ap(
357361
llvm::MemoryBuffer::getMemBuffer(source_string));
358-
swift::ide::SourceCompleteResult result =
359-
swift::ide::isSourceInputComplete(std::move(source_buffer_ap),
360-
swift::SourceFileKind::Main);
362+
363+
auto *swift_ast = getSwiftASTContext();
364+
if (!swift_ast)
365+
return LLDB_INVALID_OFFSET;
366+
367+
swift::ide::SourceCompleteResult result = swift::ide::isSourceInputComplete(
368+
std::move(source_buffer_ap), swift::SourceFileKind::Main,
369+
swift_ast->GetLanguageOptions());
361370

362371
int desired_indent =
363372
(result.IndentLevel * tab_size) + result.IndentPrefix.length();
@@ -551,21 +560,19 @@ bool SwiftREPL::PrintOneVariable(Debugger &debugger, StreamFileSP &output_sp,
551560
return handled;
552561
}
553562

554-
void SwiftREPL::CompleteCode(const std::string &current_code,
555-
CompletionRequest &request) {
563+
SwiftASTContextForExpressions *SwiftREPL::getSwiftASTContext() {
556564
//----------------------------------------------------------------------g
557565
// If we use the target's SwiftASTContext for completion, it reaaallly
558566
// slows down subsequent expressions. The compiler team doesn't have time
559567
// to fix this issue currently, so we need to work around it by making
560568
// our own copy of the AST and using this separate AST for completion.
561569
//----------------------------------------------------------------------
562-
Status error;
563570
if (!m_swift_ast) {
564571
auto type_system_or_err =
565572
m_target.GetScratchTypeSystemForLanguage(eLanguageTypeSwift);
566573
if (!type_system_or_err) {
567574
llvm::consumeError(type_system_or_err.takeError());
568-
return;
575+
return nullptr;
569576
}
570577
auto *swift_ts =
571578
llvm::dyn_cast_or_null<TypeSystemSwiftTypeRefForExpressions>(
@@ -576,82 +583,88 @@ void SwiftREPL::CompleteCode(const std::string &current_code,
576583
m_target.shared_from_this(), m_target.GetExecutableModule())));
577584
m_swift_ast = target_swift_ast;
578585
}
579-
SwiftASTContextForExpressions *swift_ast = m_swift_ast;
580-
581-
if (swift_ast) {
582-
ThreadSafeASTContext ast = swift_ast->GetASTContext();
583-
swift::REPLCompletions completions;
584-
SourceModule completion_module_info;
585-
completion_module_info.path.push_back(ConstString("repl"));
586-
swift::ModuleDecl *repl_module = nullptr;
587-
if (m_completion_module_initialized)
588-
repl_module = swift_ast->GetModule(completion_module_info, error);
589-
if (repl_module == nullptr) {
590-
swift::ImplicitImportInfo importInfo;
591-
importInfo.StdlibKind = swift::ImplicitStdlibKind::Stdlib;
592-
repl_module = swift_ast->CreateModule(completion_module_info, error,
593-
importInfo);
594-
auto bufferID = (*ast)->SourceMgr.addMemBufferCopy("// swift repl\n");
595-
swift::SourceFile *repl_source_file = new (**ast) swift::SourceFile(
596-
*repl_module, swift::SourceFileKind::Main, bufferID);
597-
repl_module->addFile(*repl_source_file);
598-
swift::performImportResolution(*repl_source_file);
599-
m_completion_module_initialized = true;
586+
return m_swift_ast;
587+
}
588+
589+
void SwiftREPL::CompleteCode(const std::string &current_code,
590+
CompletionRequest &request) {
591+
auto *swift_ast = getSwiftASTContext();
592+
if (!swift_ast)
593+
return;
594+
595+
Status error;
596+
ThreadSafeASTContext ast = swift_ast->GetASTContext();
597+
swift::REPLCompletions completions;
598+
SourceModule completion_module_info;
599+
completion_module_info.path.push_back(ConstString("repl"));
600+
swift::ModuleDecl *repl_module = nullptr;
601+
if (m_completion_module_initialized)
602+
repl_module = swift_ast->GetModule(completion_module_info, error);
603+
if (!repl_module) {
604+
swift::ImplicitImportInfo importInfo;
605+
importInfo.StdlibKind = swift::ImplicitStdlibKind::Stdlib;
606+
repl_module = swift_ast->CreateModule(completion_module_info, error,
607+
importInfo);
608+
auto bufferID = (*ast)->SourceMgr.addMemBufferCopy("// swift repl\n");
609+
swift::SourceFile *repl_source_file = new (**ast) swift::SourceFile(
610+
*repl_module, swift::SourceFileKind::Main, bufferID);
611+
repl_module->addFile(*repl_source_file);
612+
swift::performImportResolution(*repl_source_file);
613+
m_completion_module_initialized = true;
614+
}
615+
if (repl_module) {
616+
swift::SourceFile &repl_source_file = repl_module->getMainSourceFile();
617+
618+
// Swift likes to give us strings to append to the current token but
619+
// the CompletionRequest requires a replacement for the full current
620+
// token. Fix this by getting the current token here and we attach
621+
// the suffix we get from Swift.
622+
std::string prefix = request.GetCursorArgumentPrefix().str();
623+
llvm::StringRef current_code_ref(current_code);
624+
completions.populate(repl_source_file, current_code_ref);
625+
626+
// The root is the unique completion we need to use, so let's add it
627+
// to the completion list. As the completion is unique we can stop here.
628+
llvm::StringRef root = completions.getRoot();
629+
if (!root.empty()) {
630+
request.AddCompletion(prefix + root.str(), "", CompletionMode::Partial);
631+
return;
600632
}
601-
if (repl_module) {
602-
swift::SourceFile &repl_source_file =
603-
repl_module->getMainSourceFile();
604-
605-
// Swift likes to give us strings to append to the current token but
606-
// the CompletionRequest requires a replacement for the full current
607-
// token. Fix this by getting the current token here and we attach
608-
// the suffix we get from Swift.
609-
std::string prefix = request.GetCursorArgumentPrefix().str();
610-
llvm::StringRef current_code_ref(current_code);
611-
completions.populate(repl_source_file, current_code_ref);
612-
613-
// The root is the unique completion we need to use, so let's add it
614-
// to the completion list. As the completion is unique we can stop here.
615-
llvm::StringRef root = completions.getRoot();
616-
if (!root.empty()) {
617-
request.AddCompletion(prefix + root.str(), "", CompletionMode::Partial);
618-
return;
619-
}
620633

621-
// Otherwise, advance through the completion state machine.
622-
const swift::CompletionState completion_state = completions.getState();
623-
switch (completion_state) {
624-
case swift::CompletionState::CompletedRoot: {
625-
// Display the completion list.
626-
llvm::ArrayRef<llvm::StringRef> llvm_matches =
627-
completions.getCompletionList();
628-
for (const auto &llvm_match : llvm_matches) {
629-
// The completions here aren't really useful for actually completing
630-
// the token but are more descriptive hints for the user
631-
// (e.g. "isMultiple(of: Int) -> Bool"). They aren't useful for
632-
// actually completing anything so let's use the current token as
633-
// a placeholder that is always valid.
634-
if (!llvm_match.empty())
635-
request.AddCompletion(prefix, llvm_match);
636-
}
637-
} break;
634+
// Otherwise, advance through the completion state machine.
635+
const swift::CompletionState completion_state = completions.getState();
636+
switch (completion_state) {
637+
case swift::CompletionState::CompletedRoot: {
638+
// Display the completion list.
639+
llvm::ArrayRef<llvm::StringRef> llvm_matches =
640+
completions.getCompletionList();
641+
for (const auto &llvm_match : llvm_matches) {
642+
// The completions here aren't really useful for actually completing
643+
// the token but are more descriptive hints for the user
644+
// (e.g. "isMultiple(of: Int) -> Bool"). They aren't useful for
645+
// actually completing anything so let's use the current token as
646+
// a placeholder that is always valid.
647+
if (!llvm_match.empty())
648+
request.AddCompletion(prefix, llvm_match);
649+
}
650+
} break;
638651

639-
case swift::CompletionState::DisplayedCompletionList: {
640-
// Complete the next completion stem in the cycle.
641-
request.AddCompletion(prefix + completions.getPreviousStem().InsertableString.str());
642-
} break;
652+
case swift::CompletionState::DisplayedCompletionList: {
653+
// Complete the next completion stem in the cycle.
654+
request.AddCompletion(
655+
prefix + completions.getPreviousStem().InsertableString.str());
656+
} break;
643657

644-
case swift::CompletionState::Empty:
645-
case swift::CompletionState::Unique: {
646-
llvm::StringRef root = completions.getRoot();
658+
case swift::CompletionState::Empty:
659+
case swift::CompletionState::Unique: {
660+
llvm::StringRef root = completions.getRoot();
647661

648-
if (!root.empty())
649-
request.AddCompletion(prefix + root.str());
650-
} break;
662+
if (!root.empty())
663+
request.AddCompletion(prefix + root.str());
664+
} break;
651665

652-
case swift::CompletionState::Invalid:
653-
llvm_unreachable("got an invalid completion set?!");
654-
}
666+
case swift::CompletionState::Invalid:
667+
llvm_unreachable("got an invalid completion set?!");
655668
}
656669
}
657670
}

lldb/source/Plugins/ExpressionParser/Swift/SwiftREPL.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ class SwiftREPL : public REPL {
7070
lldb::ValueObjectSP &valobj_sp,
7171
ExpressionVariable *var = nullptr) override;
7272

73+
/// Retrieve the SwiftASTContext to use for completion and line parsing
74+
/// checks.
75+
SwiftASTContextForExpressions *getSwiftASTContext();
76+
7377
void CompleteCode(const std::string &current_code,
7478
CompletionRequest &request) override;
7579

0 commit comments

Comments
 (0)