@@ -320,9 +320,13 @@ llvm::StringRef SwiftREPL::GetSourceFileBasename() {
320320bool 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 ¤t_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 ¤t_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 ¤t_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}
0 commit comments