180814287SRaphael Isemann //===-- CommandCompletions.cpp --------------------------------------------===// 2c9af18a5SGreg Clayton // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6c9af18a5SGreg Clayton // 7c9af18a5SGreg Clayton //===----------------------------------------------------------------------===// 8c9af18a5SGreg Clayton 9c8ecc2a9SEugene Zelenko #include "llvm/ADT/SmallString.h" 102cc5a18dSZachary Turner #include "llvm/ADT/StringSet.h" 11c8ecc2a9SEugene Zelenko 124f3559dbSGongyu Deng #include "lldb/Breakpoint/Watchpoint.h" 139b62fd2fSGreg Clayton #include "lldb/Core/FileSpecList.h" 141f746071SGreg Clayton #include "lldb/Core/Module.h" 15190fadcdSZachary Turner #include "lldb/Core/PluginManager.h" 16190fadcdSZachary Turner #include "lldb/Host/FileSystem.h" 179b62fd2fSGreg Clayton #include "lldb/Interpreter/CommandCompletions.h" 189b62fd2fSGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h" 19633a29cfSZachary Turner #include "lldb/Interpreter/OptionValueProperties.h" 201f746071SGreg Clayton #include "lldb/Symbol/CompileUnit.h" 21f21feadcSGreg Clayton #include "lldb/Symbol/Variable.h" 223ce57e01SGongyu Deng #include "lldb/Target/Language.h" 23a952fe23SGongyu Deng #include "lldb/Target/Process.h" 24a14f4a75SGongyu Deng #include "lldb/Target/RegisterContext.h" 2566fa73faSGongyu Deng #include "lldb/Target/Thread.h" 265713a05bSZachary Turner #include "lldb/Utility/FileSpec.h" 272f3df613SZachary Turner #include "lldb/Utility/StreamString.h" 282cc5a18dSZachary Turner #include "lldb/Utility/TildeExpressionResolver.h" 29c9af18a5SGreg Clayton 307d86ee5aSZachary Turner #include "llvm/Support/FileSystem.h" 312cc5a18dSZachary Turner #include "llvm/Support/Path.h" 32190fadcdSZachary Turner 33c9af18a5SGreg Clayton using namespace lldb_private; 34c9af18a5SGreg Clayton 35440460f1SRaphael Isemann // This is the command completion callback that is used to complete the 36440460f1SRaphael Isemann // argument of the option it is bound to (in the OptionDefinition table 37440460f1SRaphael Isemann // below). 38440460f1SRaphael Isemann typedef void (*CompletionCallback)(CommandInterpreter &interpreter, 39440460f1SRaphael Isemann CompletionRequest &request, 40440460f1SRaphael Isemann // A search filter to limit the search... 41440460f1SRaphael Isemann lldb_private::SearchFilter *searcher); 42440460f1SRaphael Isemann 43440460f1SRaphael Isemann struct CommonCompletionElement { 44440460f1SRaphael Isemann uint32_t type; 45440460f1SRaphael Isemann CompletionCallback callback; 46440460f1SRaphael Isemann }; 47440460f1SRaphael Isemann 48440460f1SRaphael Isemann bool CommandCompletions::InvokeCommonCompletionCallbacks( 49440460f1SRaphael Isemann CommandInterpreter &interpreter, uint32_t completion_mask, 50440460f1SRaphael Isemann CompletionRequest &request, SearchFilter *searcher) { 51440460f1SRaphael Isemann bool handled = false; 52440460f1SRaphael Isemann 53440460f1SRaphael Isemann const CommonCompletionElement common_completions[] = { 54c9af18a5SGreg Clayton {eSourceFileCompletion, CommandCompletions::SourceFiles}, 55558ce124SJim Ingham {eDiskFileCompletion, CommandCompletions::DiskFiles}, 56558ce124SJim Ingham {eDiskDirectoryCompletion, CommandCompletions::DiskDirectories}, 57c9af18a5SGreg Clayton {eSymbolCompletion, CommandCompletions::Symbols}, 58c9af18a5SGreg Clayton {eModuleCompletion, CommandCompletions::Modules}, 59419f1be7SGongyu Deng {eModuleUUIDCompletion, CommandCompletions::ModuleUUIDs}, 603df9a8dfSCaroline Tice {eSettingsNameCompletion, CommandCompletions::SettingsNames}, 61ab65b34fSGreg Clayton {ePlatformPluginCompletion, CommandCompletions::PlatformPluginNames}, 62ab65b34fSGreg Clayton {eArchitectureCompletion, CommandCompletions::ArchitectureNames}, 63f21feadcSGreg Clayton {eVariablePathCompletion, CommandCompletions::VariablePath}, 64a14f4a75SGongyu Deng {eRegisterCompletion, CommandCompletions::Registers}, 650e50b9a4SGongyu Deng {eBreakpointCompletion, CommandCompletions::Breakpoints}, 66763bc230SGongyu Deng {eProcessPluginCompletion, CommandCompletions::ProcessPluginNames}, 678a5e2969SGongyu Deng {eDisassemblyFlavorCompletion, CommandCompletions::DisassemblyFlavors}, 683ce57e01SGongyu Deng {eTypeLanguageCompletion, CommandCompletions::TypeLanguages}, 6966fa73faSGongyu Deng {eFrameIndexCompletion, CommandCompletions::FrameIndexes}, 70b2b7dbb4SGongyu Deng {eStopHookIDCompletion, CommandCompletions::StopHookIDs}, 71a952fe23SGongyu Deng {eThreadIndexCompletion, CommandCompletions::ThreadIndexes}, 724f3559dbSGongyu Deng {eWatchPointIDCompletion, CommandCompletions::WatchPointIDs}, 73*22e63cbaSGongyu Deng {eBreakpointNameCompletion, CommandCompletions::BreakpointNames}, 74c8ecc2a9SEugene Zelenko {eNoCompletion, nullptr} // This one has to be last in the list. 75c9af18a5SGreg Clayton }; 76c9af18a5SGreg Clayton 77b9c1b51eSKate Stone for (int i = 0;; i++) { 78440460f1SRaphael Isemann if (common_completions[i].type == eNoCompletion) 79c9af18a5SGreg Clayton break; 80440460f1SRaphael Isemann else if ((common_completions[i].type & completion_mask) == 81440460f1SRaphael Isemann common_completions[i].type && 82440460f1SRaphael Isemann common_completions[i].callback != nullptr) { 83c9af18a5SGreg Clayton handled = true; 84440460f1SRaphael Isemann common_completions[i].callback(interpreter, request, searcher); 85c9af18a5SGreg Clayton } 86c9af18a5SGreg Clayton } 87c9af18a5SGreg Clayton return handled; 88c9af18a5SGreg Clayton } 89c9af18a5SGreg Clayton 90572fc897SRaphael Isemann namespace { 91572fc897SRaphael Isemann // The Completer class is a convenient base class for building searchers that 92572fc897SRaphael Isemann // go along with the SearchFilter passed to the standard Completer functions. 93572fc897SRaphael Isemann class Completer : public Searcher { 94572fc897SRaphael Isemann public: 95572fc897SRaphael Isemann Completer(CommandInterpreter &interpreter, CompletionRequest &request) 96572fc897SRaphael Isemann : m_interpreter(interpreter), m_request(request) {} 97572fc897SRaphael Isemann 98572fc897SRaphael Isemann ~Completer() override = default; 99572fc897SRaphael Isemann 100572fc897SRaphael Isemann CallbackReturn SearchCallback(SearchFilter &filter, SymbolContext &context, 101572fc897SRaphael Isemann Address *addr) override = 0; 102572fc897SRaphael Isemann 103572fc897SRaphael Isemann lldb::SearchDepth GetDepth() override = 0; 104572fc897SRaphael Isemann 105572fc897SRaphael Isemann virtual void DoCompletion(SearchFilter *filter) = 0; 106572fc897SRaphael Isemann 107572fc897SRaphael Isemann protected: 108572fc897SRaphael Isemann CommandInterpreter &m_interpreter; 109572fc897SRaphael Isemann CompletionRequest &m_request; 110572fc897SRaphael Isemann 111572fc897SRaphael Isemann private: 112eaebcbc6SKonrad Kleine Completer(const Completer &) = delete; 113eaebcbc6SKonrad Kleine const Completer &operator=(const Completer &) = delete; 114572fc897SRaphael Isemann }; 115572fc897SRaphael Isemann } // namespace 116572fc897SRaphael Isemann 117572fc897SRaphael Isemann // SourceFileCompleter implements the source file completer 118572fc897SRaphael Isemann namespace { 119572fc897SRaphael Isemann class SourceFileCompleter : public Completer { 120572fc897SRaphael Isemann public: 121572fc897SRaphael Isemann SourceFileCompleter(CommandInterpreter &interpreter, 122572fc897SRaphael Isemann CompletionRequest &request) 123572fc897SRaphael Isemann : Completer(interpreter, request), m_matching_files() { 124572fc897SRaphael Isemann FileSpec partial_spec(m_request.GetCursorArgumentPrefix()); 125572fc897SRaphael Isemann m_file_name = partial_spec.GetFilename().GetCString(); 126572fc897SRaphael Isemann m_dir_name = partial_spec.GetDirectory().GetCString(); 127572fc897SRaphael Isemann } 128572fc897SRaphael Isemann 129572fc897SRaphael Isemann lldb::SearchDepth GetDepth() override { return lldb::eSearchDepthCompUnit; } 130572fc897SRaphael Isemann 131572fc897SRaphael Isemann Searcher::CallbackReturn SearchCallback(SearchFilter &filter, 132572fc897SRaphael Isemann SymbolContext &context, 133572fc897SRaphael Isemann Address *addr) override { 134572fc897SRaphael Isemann if (context.comp_unit != nullptr) { 135572fc897SRaphael Isemann const char *cur_file_name = 136572fc897SRaphael Isemann context.comp_unit->GetPrimaryFile().GetFilename().GetCString(); 137572fc897SRaphael Isemann const char *cur_dir_name = 138572fc897SRaphael Isemann context.comp_unit->GetPrimaryFile().GetDirectory().GetCString(); 139572fc897SRaphael Isemann 140572fc897SRaphael Isemann bool match = false; 141572fc897SRaphael Isemann if (m_file_name && cur_file_name && 142572fc897SRaphael Isemann strstr(cur_file_name, m_file_name) == cur_file_name) 143572fc897SRaphael Isemann match = true; 144572fc897SRaphael Isemann 145572fc897SRaphael Isemann if (match && m_dir_name && cur_dir_name && 146572fc897SRaphael Isemann strstr(cur_dir_name, m_dir_name) != cur_dir_name) 147572fc897SRaphael Isemann match = false; 148572fc897SRaphael Isemann 149572fc897SRaphael Isemann if (match) { 150572fc897SRaphael Isemann m_matching_files.AppendIfUnique(context.comp_unit->GetPrimaryFile()); 151572fc897SRaphael Isemann } 152572fc897SRaphael Isemann } 153572fc897SRaphael Isemann return Searcher::eCallbackReturnContinue; 154572fc897SRaphael Isemann } 155572fc897SRaphael Isemann 156572fc897SRaphael Isemann void DoCompletion(SearchFilter *filter) override { 157572fc897SRaphael Isemann filter->Search(*this); 158572fc897SRaphael Isemann // Now convert the filelist to completions: 159572fc897SRaphael Isemann for (size_t i = 0; i < m_matching_files.GetSize(); i++) { 160572fc897SRaphael Isemann m_request.AddCompletion( 161572fc897SRaphael Isemann m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString()); 162572fc897SRaphael Isemann } 163572fc897SRaphael Isemann } 164572fc897SRaphael Isemann 165572fc897SRaphael Isemann private: 166572fc897SRaphael Isemann FileSpecList m_matching_files; 167572fc897SRaphael Isemann const char *m_file_name; 168572fc897SRaphael Isemann const char *m_dir_name; 169572fc897SRaphael Isemann 170eaebcbc6SKonrad Kleine SourceFileCompleter(const SourceFileCompleter &) = delete; 171eaebcbc6SKonrad Kleine const SourceFileCompleter &operator=(const SourceFileCompleter &) = delete; 172572fc897SRaphael Isemann }; 173572fc897SRaphael Isemann } // namespace 174572fc897SRaphael Isemann 175572fc897SRaphael Isemann static bool regex_chars(const char comp) { 176572fc897SRaphael Isemann return llvm::StringRef("[](){}+.*|^$\\?").contains(comp); 177572fc897SRaphael Isemann } 178572fc897SRaphael Isemann 179572fc897SRaphael Isemann namespace { 180572fc897SRaphael Isemann class SymbolCompleter : public Completer { 181572fc897SRaphael Isemann 182572fc897SRaphael Isemann public: 183572fc897SRaphael Isemann SymbolCompleter(CommandInterpreter &interpreter, CompletionRequest &request) 184572fc897SRaphael Isemann : Completer(interpreter, request) { 185572fc897SRaphael Isemann std::string regex_str; 186572fc897SRaphael Isemann if (!m_request.GetCursorArgumentPrefix().empty()) { 187572fc897SRaphael Isemann regex_str.append("^"); 188572fc897SRaphael Isemann regex_str.append(std::string(m_request.GetCursorArgumentPrefix())); 189572fc897SRaphael Isemann } else { 190572fc897SRaphael Isemann // Match anything since the completion string is empty 191572fc897SRaphael Isemann regex_str.append("."); 192572fc897SRaphael Isemann } 193572fc897SRaphael Isemann std::string::iterator pos = 194572fc897SRaphael Isemann find_if(regex_str.begin() + 1, regex_str.end(), regex_chars); 195572fc897SRaphael Isemann while (pos < regex_str.end()) { 196572fc897SRaphael Isemann pos = regex_str.insert(pos, '\\'); 197572fc897SRaphael Isemann pos = find_if(pos + 2, regex_str.end(), regex_chars); 198572fc897SRaphael Isemann } 199572fc897SRaphael Isemann m_regex = RegularExpression(regex_str); 200572fc897SRaphael Isemann } 201572fc897SRaphael Isemann 202572fc897SRaphael Isemann lldb::SearchDepth GetDepth() override { return lldb::eSearchDepthModule; } 203572fc897SRaphael Isemann 204572fc897SRaphael Isemann Searcher::CallbackReturn SearchCallback(SearchFilter &filter, 205572fc897SRaphael Isemann SymbolContext &context, 206572fc897SRaphael Isemann Address *addr) override { 207572fc897SRaphael Isemann if (context.module_sp) { 208572fc897SRaphael Isemann SymbolContextList sc_list; 209572fc897SRaphael Isemann const bool include_symbols = true; 210572fc897SRaphael Isemann const bool include_inlines = true; 211572fc897SRaphael Isemann context.module_sp->FindFunctions(m_regex, include_symbols, 212572fc897SRaphael Isemann include_inlines, sc_list); 213572fc897SRaphael Isemann 214572fc897SRaphael Isemann SymbolContext sc; 215572fc897SRaphael Isemann // Now add the functions & symbols to the list - only add if unique: 216572fc897SRaphael Isemann for (uint32_t i = 0; i < sc_list.GetSize(); i++) { 217572fc897SRaphael Isemann if (sc_list.GetContextAtIndex(i, sc)) { 218572fc897SRaphael Isemann ConstString func_name = sc.GetFunctionName(Mangled::ePreferDemangled); 219572fc897SRaphael Isemann // Ensure that the function name matches the regex. This is more than 220572fc897SRaphael Isemann // a sanity check. It is possible that the demangled function name 221572fc897SRaphael Isemann // does not start with the prefix, for example when it's in an 222572fc897SRaphael Isemann // anonymous namespace. 223572fc897SRaphael Isemann if (!func_name.IsEmpty() && m_regex.Execute(func_name.GetStringRef())) 224572fc897SRaphael Isemann m_match_set.insert(func_name); 225572fc897SRaphael Isemann } 226572fc897SRaphael Isemann } 227572fc897SRaphael Isemann } 228572fc897SRaphael Isemann return Searcher::eCallbackReturnContinue; 229572fc897SRaphael Isemann } 230572fc897SRaphael Isemann 231572fc897SRaphael Isemann void DoCompletion(SearchFilter *filter) override { 232572fc897SRaphael Isemann filter->Search(*this); 233572fc897SRaphael Isemann collection::iterator pos = m_match_set.begin(), end = m_match_set.end(); 234572fc897SRaphael Isemann for (pos = m_match_set.begin(); pos != end; pos++) 235572fc897SRaphael Isemann m_request.AddCompletion((*pos).GetCString()); 236572fc897SRaphael Isemann } 237572fc897SRaphael Isemann 238572fc897SRaphael Isemann private: 239572fc897SRaphael Isemann RegularExpression m_regex; 240572fc897SRaphael Isemann typedef std::set<ConstString> collection; 241572fc897SRaphael Isemann collection m_match_set; 242572fc897SRaphael Isemann 243eaebcbc6SKonrad Kleine SymbolCompleter(const SymbolCompleter &) = delete; 244eaebcbc6SKonrad Kleine const SymbolCompleter &operator=(const SymbolCompleter &) = delete; 245572fc897SRaphael Isemann }; 246572fc897SRaphael Isemann } // namespace 247572fc897SRaphael Isemann 248572fc897SRaphael Isemann namespace { 249572fc897SRaphael Isemann class ModuleCompleter : public Completer { 250572fc897SRaphael Isemann public: 251572fc897SRaphael Isemann ModuleCompleter(CommandInterpreter &interpreter, CompletionRequest &request) 252572fc897SRaphael Isemann : Completer(interpreter, request) { 253572fc897SRaphael Isemann FileSpec partial_spec(m_request.GetCursorArgumentPrefix()); 254572fc897SRaphael Isemann m_file_name = partial_spec.GetFilename().GetCString(); 255572fc897SRaphael Isemann m_dir_name = partial_spec.GetDirectory().GetCString(); 256572fc897SRaphael Isemann } 257572fc897SRaphael Isemann 258572fc897SRaphael Isemann lldb::SearchDepth GetDepth() override { return lldb::eSearchDepthModule; } 259572fc897SRaphael Isemann 260572fc897SRaphael Isemann Searcher::CallbackReturn SearchCallback(SearchFilter &filter, 261572fc897SRaphael Isemann SymbolContext &context, 262572fc897SRaphael Isemann Address *addr) override { 263572fc897SRaphael Isemann if (context.module_sp) { 264572fc897SRaphael Isemann const char *cur_file_name = 265572fc897SRaphael Isemann context.module_sp->GetFileSpec().GetFilename().GetCString(); 266572fc897SRaphael Isemann const char *cur_dir_name = 267572fc897SRaphael Isemann context.module_sp->GetFileSpec().GetDirectory().GetCString(); 268572fc897SRaphael Isemann 269572fc897SRaphael Isemann bool match = false; 270572fc897SRaphael Isemann if (m_file_name && cur_file_name && 271572fc897SRaphael Isemann strstr(cur_file_name, m_file_name) == cur_file_name) 272572fc897SRaphael Isemann match = true; 273572fc897SRaphael Isemann 274572fc897SRaphael Isemann if (match && m_dir_name && cur_dir_name && 275572fc897SRaphael Isemann strstr(cur_dir_name, m_dir_name) != cur_dir_name) 276572fc897SRaphael Isemann match = false; 277572fc897SRaphael Isemann 278572fc897SRaphael Isemann if (match) { 279572fc897SRaphael Isemann m_request.AddCompletion(cur_file_name); 280572fc897SRaphael Isemann } 281572fc897SRaphael Isemann } 282572fc897SRaphael Isemann return Searcher::eCallbackReturnContinue; 283572fc897SRaphael Isemann } 284572fc897SRaphael Isemann 285572fc897SRaphael Isemann void DoCompletion(SearchFilter *filter) override { filter->Search(*this); } 286572fc897SRaphael Isemann 287572fc897SRaphael Isemann private: 288572fc897SRaphael Isemann const char *m_file_name; 289572fc897SRaphael Isemann const char *m_dir_name; 290572fc897SRaphael Isemann 291eaebcbc6SKonrad Kleine ModuleCompleter(const ModuleCompleter &) = delete; 292eaebcbc6SKonrad Kleine const ModuleCompleter &operator=(const ModuleCompleter &) = delete; 293572fc897SRaphael Isemann }; 294572fc897SRaphael Isemann } // namespace 295572fc897SRaphael Isemann 296ae34ed2cSRaphael Isemann void CommandCompletions::SourceFiles(CommandInterpreter &interpreter, 297a2e76c0bSRaphael Isemann CompletionRequest &request, 298a2e76c0bSRaphael Isemann SearchFilter *searcher) { 29962174682SRaphael Isemann SourceFileCompleter completer(interpreter, request); 300c9af18a5SGreg Clayton 301b9c1b51eSKate Stone if (searcher == nullptr) { 3022976d00aSJim Ingham lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget(); 30333df7cd3SJim Ingham SearchFilterForUnconstrainedSearches null_searcher(target_sp); 304c9af18a5SGreg Clayton completer.DoCompletion(&null_searcher); 305b9c1b51eSKate Stone } else { 306c9af18a5SGreg Clayton completer.DoCompletion(searcher); 307c9af18a5SGreg Clayton } 308c9af18a5SGreg Clayton } 309c9af18a5SGreg Clayton 310ae34ed2cSRaphael Isemann static void DiskFilesOrDirectories(const llvm::Twine &partial_name, 3115edee822SRaphael Isemann bool only_directories, 3125edee822SRaphael Isemann CompletionRequest &request, 3132cc5a18dSZachary Turner TildeExpressionResolver &Resolver) { 3142cc5a18dSZachary Turner llvm::SmallString<256> CompletionBuffer; 3152cc5a18dSZachary Turner llvm::SmallString<256> Storage; 3162cc5a18dSZachary Turner partial_name.toVector(CompletionBuffer); 317b2f1fb29SVirgile Bello 3182cc5a18dSZachary Turner if (CompletionBuffer.size() >= PATH_MAX) 319ae34ed2cSRaphael Isemann return; 320b2f1fb29SVirgile Bello 3212cc5a18dSZachary Turner namespace path = llvm::sys::path; 322b2f1fb29SVirgile Bello 3232cc5a18dSZachary Turner llvm::StringRef SearchDir; 3242cc5a18dSZachary Turner llvm::StringRef PartialItem; 3252cc5a18dSZachary Turner 3262cc5a18dSZachary Turner if (CompletionBuffer.startswith("~")) { 3272cc5a18dSZachary Turner llvm::StringRef Buffer(CompletionBuffer); 3285c5091fcSZachary Turner size_t FirstSep = 3295c5091fcSZachary Turner Buffer.find_if([](char c) { return path::is_separator(c); }); 3302cc5a18dSZachary Turner 3312cc5a18dSZachary Turner llvm::StringRef Username = Buffer.take_front(FirstSep); 3322cc5a18dSZachary Turner llvm::StringRef Remainder; 3332cc5a18dSZachary Turner if (FirstSep != llvm::StringRef::npos) 3342cc5a18dSZachary Turner Remainder = Buffer.drop_front(FirstSep + 1); 3352cc5a18dSZachary Turner 336b3f44ad9SStella Stamenova llvm::SmallString<256> Resolved; 3372cc5a18dSZachary Turner if (!Resolver.ResolveExact(Username, Resolved)) { 3382cc5a18dSZachary Turner // We couldn't resolve it as a full username. If there were no slashes 3392cc5a18dSZachary Turner // then this might be a partial username. We try to resolve it as such 3402cc5a18dSZachary Turner // but after that, we're done regardless of any matches. 3412cc5a18dSZachary Turner if (FirstSep == llvm::StringRef::npos) { 3422cc5a18dSZachary Turner llvm::StringSet<> MatchSet; 343a2e76c0bSRaphael Isemann Resolver.ResolvePartial(Username, MatchSet); 3442cc5a18dSZachary Turner for (const auto &S : MatchSet) { 3452cc5a18dSZachary Turner Resolved = S.getKey(); 3462cc5a18dSZachary Turner path::append(Resolved, path::get_separator()); 3475edee822SRaphael Isemann request.AddCompletion(Resolved, "", CompletionMode::Partial); 348b2f1fb29SVirgile Bello } 349b2f1fb29SVirgile Bello } 350ae34ed2cSRaphael Isemann return; 3512cc5a18dSZachary Turner } 3520734e6a5SZachary Turner 35305097246SAdrian Prantl // If there was no trailing slash, then we're done as soon as we resolve 35405097246SAdrian Prantl // the expression to the correct directory. Otherwise we need to continue 3552cc5a18dSZachary Turner // looking for matches within that directory. 3562cc5a18dSZachary Turner if (FirstSep == llvm::StringRef::npos) { 3572cc5a18dSZachary Turner // Make sure it ends with a separator. 3582cc5a18dSZachary Turner path::append(CompletionBuffer, path::get_separator()); 3595edee822SRaphael Isemann request.AddCompletion(CompletionBuffer, "", CompletionMode::Partial); 360ae34ed2cSRaphael Isemann return; 3612cc5a18dSZachary Turner } 3622cc5a18dSZachary Turner 3632cc5a18dSZachary Turner // We want to keep the form the user typed, so we special case this to 3642cc5a18dSZachary Turner // search in the fully resolved directory, but CompletionBuffer keeps the 3652cc5a18dSZachary Turner // unmodified form that the user typed. 3662cc5a18dSZachary Turner Storage = Resolved; 36788ec2e4eSPavel Labath llvm::StringRef RemainderDir = path::parent_path(Remainder); 3684621e0b0SRaphael Isemann if (!RemainderDir.empty()) { 3694621e0b0SRaphael Isemann // Append the remaining path to the resolved directory. 3704621e0b0SRaphael Isemann Storage.append(path::get_separator()); 3714621e0b0SRaphael Isemann Storage.append(RemainderDir); 3724621e0b0SRaphael Isemann } 37317843885SRaphael Isemann SearchDir = Storage; 3740734e6a5SZachary Turner } else { 3752cc5a18dSZachary Turner SearchDir = path::parent_path(CompletionBuffer); 3762cc5a18dSZachary Turner } 3772cc5a18dSZachary Turner 3782cc5a18dSZachary Turner size_t FullPrefixLen = CompletionBuffer.size(); 3792cc5a18dSZachary Turner 3802cc5a18dSZachary Turner PartialItem = path::filename(CompletionBuffer); 38178a10a7aSFrederic Riss 38278a10a7aSFrederic Riss // path::filename() will return "." when the passed path ends with a 38378a10a7aSFrederic Riss // directory separator. We have to filter those out, but only when the 38478a10a7aSFrederic Riss // "." doesn't come from the completion request itself. 38578a10a7aSFrederic Riss if (PartialItem == "." && path::is_separator(CompletionBuffer.back())) 3862cc5a18dSZachary Turner PartialItem = llvm::StringRef(); 3872cc5a18dSZachary Turner 388426d1379SZachary Turner if (SearchDir.empty()) { 389426d1379SZachary Turner llvm::sys::fs::current_path(Storage); 390426d1379SZachary Turner SearchDir = Storage; 391426d1379SZachary Turner } 3922cc5a18dSZachary Turner assert(!PartialItem.contains(path::get_separator())); 3932cc5a18dSZachary Turner 3942cc5a18dSZachary Turner // SearchDir now contains the directory to search in, and Prefix contains the 3952cc5a18dSZachary Turner // text we want to match against items in that directory. 3962cc5a18dSZachary Turner 397edaf2bccSJonas Devlieghere FileSystem &fs = FileSystem::Instance(); 3982cc5a18dSZachary Turner std::error_code EC; 399edaf2bccSJonas Devlieghere llvm::vfs::directory_iterator Iter = fs.DirBegin(SearchDir, EC); 400edaf2bccSJonas Devlieghere llvm::vfs::directory_iterator End; 4012cc5a18dSZachary Turner for (; Iter != End && !EC; Iter.increment(EC)) { 4022cc5a18dSZachary Turner auto &Entry = *Iter; 403edaf2bccSJonas Devlieghere llvm::ErrorOr<llvm::vfs::Status> Status = fs.GetStatus(Entry.path()); 404edaf2bccSJonas Devlieghere 405edaf2bccSJonas Devlieghere if (!Status) 406edaf2bccSJonas Devlieghere continue; 4072cc5a18dSZachary Turner 4082cc5a18dSZachary Turner auto Name = path::filename(Entry.path()); 4092cc5a18dSZachary Turner 4102cc5a18dSZachary Turner // Omit ".", ".." 4112cc5a18dSZachary Turner if (Name == "." || Name == ".." || !Name.startswith(PartialItem)) 4122cc5a18dSZachary Turner continue; 4132cc5a18dSZachary Turner 414edaf2bccSJonas Devlieghere bool is_dir = Status->isDirectory(); 4152cc5a18dSZachary Turner 4162cc5a18dSZachary Turner // If it's a symlink, then we treat it as a directory as long as the target 4172cc5a18dSZachary Turner // is a directory. 418edaf2bccSJonas Devlieghere if (Status->isSymlink()) { 419edaf2bccSJonas Devlieghere FileSpec symlink_filespec(Entry.path()); 420edaf2bccSJonas Devlieghere FileSpec resolved_filespec; 421edaf2bccSJonas Devlieghere auto error = fs.ResolveSymbolicLink(symlink_filespec, resolved_filespec); 422edaf2bccSJonas Devlieghere if (error.Success()) 423edaf2bccSJonas Devlieghere is_dir = fs.IsDirectory(symlink_filespec); 4242cc5a18dSZachary Turner } 425edaf2bccSJonas Devlieghere 4262cc5a18dSZachary Turner if (only_directories && !is_dir) 4272cc5a18dSZachary Turner continue; 4282cc5a18dSZachary Turner 4292cc5a18dSZachary Turner // Shrink it back down so that it just has the original prefix the user 4302cc5a18dSZachary Turner // typed and remove the part of the name which is common to the located 4312cc5a18dSZachary Turner // item and what the user typed. 4322cc5a18dSZachary Turner CompletionBuffer.resize(FullPrefixLen); 4332cc5a18dSZachary Turner Name = Name.drop_front(PartialItem.size()); 4342cc5a18dSZachary Turner CompletionBuffer.append(Name); 4352cc5a18dSZachary Turner 4362cc5a18dSZachary Turner if (is_dir) { 4372cc5a18dSZachary Turner path::append(CompletionBuffer, path::get_separator()); 4380734e6a5SZachary Turner } 4390734e6a5SZachary Turner 4405edee822SRaphael Isemann CompletionMode mode = 4415edee822SRaphael Isemann is_dir ? CompletionMode::Partial : CompletionMode::Normal; 4425edee822SRaphael Isemann request.AddCompletion(CompletionBuffer, "", mode); 443d5bd3a1eSZachary Turner } 444558ce124SJim Ingham } 445558ce124SJim Ingham 4465edee822SRaphael Isemann static void DiskFilesOrDirectories(const llvm::Twine &partial_name, 4475edee822SRaphael Isemann bool only_directories, StringList &matches, 4485edee822SRaphael Isemann TildeExpressionResolver &Resolver) { 4495edee822SRaphael Isemann CompletionResult result; 4505edee822SRaphael Isemann std::string partial_name_str = partial_name.str(); 4515edee822SRaphael Isemann CompletionRequest request(partial_name_str, partial_name_str.size(), result); 4525edee822SRaphael Isemann DiskFilesOrDirectories(partial_name, only_directories, request, Resolver); 4535edee822SRaphael Isemann result.GetMatches(matches); 4545edee822SRaphael Isemann } 4555edee822SRaphael Isemann 456ae34ed2cSRaphael Isemann static void DiskFilesOrDirectories(CompletionRequest &request, 4571a6d7ab5SRaphael Isemann bool only_directories) { 45872787ac6SJonas Devlieghere StandardTildeExpressionResolver resolver; 4591a6d7ab5SRaphael Isemann DiskFilesOrDirectories(request.GetCursorArgumentPrefix(), only_directories, 4605edee822SRaphael Isemann request, resolver); 4611a6d7ab5SRaphael Isemann } 4621a6d7ab5SRaphael Isemann 463ae34ed2cSRaphael Isemann void CommandCompletions::DiskFiles(CommandInterpreter &interpreter, 464a2e76c0bSRaphael Isemann CompletionRequest &request, 465a2e76c0bSRaphael Isemann SearchFilter *searcher) { 466ae34ed2cSRaphael Isemann DiskFilesOrDirectories(request, /*only_dirs*/ false); 4672cc5a18dSZachary Turner } 4682cc5a18dSZachary Turner 469ae34ed2cSRaphael Isemann void CommandCompletions::DiskFiles(const llvm::Twine &partial_file_name, 4702cc5a18dSZachary Turner StringList &matches, 4712cc5a18dSZachary Turner TildeExpressionResolver &Resolver) { 472ae34ed2cSRaphael Isemann DiskFilesOrDirectories(partial_file_name, false, matches, Resolver); 473558ce124SJim Ingham } 474558ce124SJim Ingham 475ae34ed2cSRaphael Isemann void CommandCompletions::DiskDirectories(CommandInterpreter &interpreter, 476a2e76c0bSRaphael Isemann CompletionRequest &request, 477a2e76c0bSRaphael Isemann SearchFilter *searcher) { 478ae34ed2cSRaphael Isemann DiskFilesOrDirectories(request, /*only_dirs*/ true); 4792cc5a18dSZachary Turner } 4802cc5a18dSZachary Turner 481ae34ed2cSRaphael Isemann void CommandCompletions::DiskDirectories(const llvm::Twine &partial_file_name, 4822cc5a18dSZachary Turner StringList &matches, 4832cc5a18dSZachary Turner TildeExpressionResolver &Resolver) { 484ae34ed2cSRaphael Isemann DiskFilesOrDirectories(partial_file_name, true, matches, Resolver); 485558ce124SJim Ingham } 486558ce124SJim Ingham 487ae34ed2cSRaphael Isemann void CommandCompletions::Modules(CommandInterpreter &interpreter, 488a2e76c0bSRaphael Isemann CompletionRequest &request, 489a2e76c0bSRaphael Isemann SearchFilter *searcher) { 490a2e76c0bSRaphael Isemann ModuleCompleter completer(interpreter, request); 491c9af18a5SGreg Clayton 492b9c1b51eSKate Stone if (searcher == nullptr) { 4932976d00aSJim Ingham lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget(); 49433df7cd3SJim Ingham SearchFilterForUnconstrainedSearches null_searcher(target_sp); 495c9af18a5SGreg Clayton completer.DoCompletion(&null_searcher); 496b9c1b51eSKate Stone } else { 497c9af18a5SGreg Clayton completer.DoCompletion(searcher); 498c9af18a5SGreg Clayton } 499c9af18a5SGreg Clayton } 500c9af18a5SGreg Clayton 501419f1be7SGongyu Deng void CommandCompletions::ModuleUUIDs(CommandInterpreter &interpreter, 502419f1be7SGongyu Deng CompletionRequest &request, 503419f1be7SGongyu Deng SearchFilter *searcher) { 504419f1be7SGongyu Deng const ExecutionContext &exe_ctx = interpreter.GetExecutionContext(); 505419f1be7SGongyu Deng if (!exe_ctx.HasTargetScope()) 506419f1be7SGongyu Deng return; 507419f1be7SGongyu Deng 508419f1be7SGongyu Deng exe_ctx.GetTargetPtr()->GetImages().ForEach( 509419f1be7SGongyu Deng [&request](const lldb::ModuleSP &module) { 510419f1be7SGongyu Deng StreamString strm; 511419f1be7SGongyu Deng module->GetDescription(strm.AsRawOstream(), 512419f1be7SGongyu Deng lldb::eDescriptionLevelInitial); 513419f1be7SGongyu Deng request.TryCompleteCurrentArg(module->GetUUID().GetAsString(), 514419f1be7SGongyu Deng strm.GetString()); 515419f1be7SGongyu Deng return true; 516419f1be7SGongyu Deng }); 517419f1be7SGongyu Deng } 518419f1be7SGongyu Deng 519ae34ed2cSRaphael Isemann void CommandCompletions::Symbols(CommandInterpreter &interpreter, 520a2e76c0bSRaphael Isemann CompletionRequest &request, 521a2e76c0bSRaphael Isemann SearchFilter *searcher) { 522a2e76c0bSRaphael Isemann SymbolCompleter completer(interpreter, request); 523c9af18a5SGreg Clayton 524b9c1b51eSKate Stone if (searcher == nullptr) { 5252976d00aSJim Ingham lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget(); 52633df7cd3SJim Ingham SearchFilterForUnconstrainedSearches null_searcher(target_sp); 527c9af18a5SGreg Clayton completer.DoCompletion(&null_searcher); 528b9c1b51eSKate Stone } else { 529c9af18a5SGreg Clayton completer.DoCompletion(searcher); 530c9af18a5SGreg Clayton } 531c9af18a5SGreg Clayton } 532c9af18a5SGreg Clayton 533ae34ed2cSRaphael Isemann void CommandCompletions::SettingsNames(CommandInterpreter &interpreter, 534a2e76c0bSRaphael Isemann CompletionRequest &request, 535a2e76c0bSRaphael Isemann SearchFilter *searcher) { 53667cc0636SGreg Clayton // Cache the full setting name list 53767cc0636SGreg Clayton static StringList g_property_names; 538b9c1b51eSKate Stone if (g_property_names.GetSize() == 0) { 53967cc0636SGreg Clayton // Generate the full setting name list on demand 540b9c1b51eSKate Stone lldb::OptionValuePropertiesSP properties_sp( 541b9c1b51eSKate Stone interpreter.GetDebugger().GetValueProperties()); 542b9c1b51eSKate Stone if (properties_sp) { 54367cc0636SGreg Clayton StreamString strm; 544c8ecc2a9SEugene Zelenko properties_sp->DumpValue(nullptr, strm, OptionValue::eDumpOptionName); 545adcd0268SBenjamin Kramer const std::string &str = std::string(strm.GetString()); 54667cc0636SGreg Clayton g_property_names.SplitIntoLines(str.c_str(), str.size()); 54767cc0636SGreg Clayton } 54867cc0636SGreg Clayton } 5493df9a8dfSCaroline Tice 55093ca36d7SRaphael Isemann for (const std::string &s : g_property_names) 55193ca36d7SRaphael Isemann request.TryCompleteCurrentArg(s); 552b8639f5cSRaphael Isemann } 553b8639f5cSRaphael Isemann 554ae34ed2cSRaphael Isemann void CommandCompletions::PlatformPluginNames(CommandInterpreter &interpreter, 555a2e76c0bSRaphael Isemann CompletionRequest &request, 556a2e76c0bSRaphael Isemann SearchFilter *searcher) { 557ae34ed2cSRaphael Isemann PluginManager::AutoCompletePlatformName(request.GetCursorArgumentPrefix(), 558ae34ed2cSRaphael Isemann request); 559ab65b34fSGreg Clayton } 560ab65b34fSGreg Clayton 561ae34ed2cSRaphael Isemann void CommandCompletions::ArchitectureNames(CommandInterpreter &interpreter, 562a2e76c0bSRaphael Isemann CompletionRequest &request, 563a2e76c0bSRaphael Isemann SearchFilter *searcher) { 564ae34ed2cSRaphael Isemann ArchSpec::AutoComplete(request); 565ab65b34fSGreg Clayton } 566ab65b34fSGreg Clayton 567ae34ed2cSRaphael Isemann void CommandCompletions::VariablePath(CommandInterpreter &interpreter, 568a2e76c0bSRaphael Isemann CompletionRequest &request, 569a2e76c0bSRaphael Isemann SearchFilter *searcher) { 570ae34ed2cSRaphael Isemann Variable::AutoComplete(interpreter.GetExecutionContext(), request); 571f21feadcSGreg Clayton } 572a14f4a75SGongyu Deng 573a14f4a75SGongyu Deng void CommandCompletions::Registers(CommandInterpreter &interpreter, 574a14f4a75SGongyu Deng CompletionRequest &request, 575a14f4a75SGongyu Deng SearchFilter *searcher) { 576a14f4a75SGongyu Deng std::string reg_prefix = ""; 577a14f4a75SGongyu Deng if (request.GetCursorArgumentPrefix().startswith("$")) 578a14f4a75SGongyu Deng reg_prefix = "$"; 579a14f4a75SGongyu Deng 580a14f4a75SGongyu Deng RegisterContext *reg_ctx = 581a14f4a75SGongyu Deng interpreter.GetExecutionContext().GetRegisterContext(); 582a14f4a75SGongyu Deng const size_t reg_num = reg_ctx->GetRegisterCount(); 583a14f4a75SGongyu Deng for (size_t reg_idx = 0; reg_idx < reg_num; ++reg_idx) { 584a14f4a75SGongyu Deng const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_idx); 585a14f4a75SGongyu Deng request.TryCompleteCurrentArg(reg_prefix + reg_info->name, 586a14f4a75SGongyu Deng reg_info->alt_name); 587a14f4a75SGongyu Deng } 588a14f4a75SGongyu Deng } 5890e50b9a4SGongyu Deng 5900e50b9a4SGongyu Deng void CommandCompletions::Breakpoints(CommandInterpreter &interpreter, 5910e50b9a4SGongyu Deng CompletionRequest &request, 5920e50b9a4SGongyu Deng SearchFilter *searcher) { 5930e50b9a4SGongyu Deng lldb::TargetSP target = interpreter.GetDebugger().GetSelectedTarget(); 5940e50b9a4SGongyu Deng if (!target) 5950e50b9a4SGongyu Deng return; 5960e50b9a4SGongyu Deng 5970e50b9a4SGongyu Deng const BreakpointList &breakpoints = target->GetBreakpointList(); 5980e50b9a4SGongyu Deng 5990e50b9a4SGongyu Deng std::unique_lock<std::recursive_mutex> lock; 6000e50b9a4SGongyu Deng target->GetBreakpointList().GetListMutex(lock); 6010e50b9a4SGongyu Deng 6020e50b9a4SGongyu Deng size_t num_breakpoints = breakpoints.GetSize(); 6030e50b9a4SGongyu Deng if (num_breakpoints == 0) 6040e50b9a4SGongyu Deng return; 6050e50b9a4SGongyu Deng 6060e50b9a4SGongyu Deng for (size_t i = 0; i < num_breakpoints; ++i) { 6070e50b9a4SGongyu Deng lldb::BreakpointSP bp = breakpoints.GetBreakpointAtIndex(i); 6080e50b9a4SGongyu Deng 6090e50b9a4SGongyu Deng StreamString s; 6100e50b9a4SGongyu Deng bp->GetDescription(&s, lldb::eDescriptionLevelBrief); 6110e50b9a4SGongyu Deng llvm::StringRef bp_info = s.GetString(); 6120e50b9a4SGongyu Deng 6130e50b9a4SGongyu Deng const size_t colon_pos = bp_info.find_first_of(':'); 6140e50b9a4SGongyu Deng if (colon_pos != llvm::StringRef::npos) 6150e50b9a4SGongyu Deng bp_info = bp_info.drop_front(colon_pos + 2); 6160e50b9a4SGongyu Deng 6170e50b9a4SGongyu Deng request.TryCompleteCurrentArg(std::to_string(bp->GetID()), bp_info); 6180e50b9a4SGongyu Deng } 6190e50b9a4SGongyu Deng } 620763bc230SGongyu Deng 621*22e63cbaSGongyu Deng void CommandCompletions::BreakpointNames(CommandInterpreter &interpreter, 622*22e63cbaSGongyu Deng CompletionRequest &request, 623*22e63cbaSGongyu Deng SearchFilter *searcher) { 624*22e63cbaSGongyu Deng lldb::TargetSP target = interpreter.GetDebugger().GetSelectedTarget(); 625*22e63cbaSGongyu Deng if (!target) 626*22e63cbaSGongyu Deng return; 627*22e63cbaSGongyu Deng 628*22e63cbaSGongyu Deng std::vector<std::string> name_list; 629*22e63cbaSGongyu Deng target->GetBreakpointNames(name_list); 630*22e63cbaSGongyu Deng 631*22e63cbaSGongyu Deng for (const std::string &name : name_list) 632*22e63cbaSGongyu Deng request.TryCompleteCurrentArg(name); 633*22e63cbaSGongyu Deng } 634*22e63cbaSGongyu Deng 635763bc230SGongyu Deng void CommandCompletions::ProcessPluginNames(CommandInterpreter &interpreter, 636763bc230SGongyu Deng CompletionRequest &request, 637763bc230SGongyu Deng SearchFilter *searcher) { 638763bc230SGongyu Deng PluginManager::AutoCompleteProcessName(request.GetCursorArgumentPrefix(), 639763bc230SGongyu Deng request); 640763bc230SGongyu Deng } 6418a5e2969SGongyu Deng void CommandCompletions::DisassemblyFlavors(CommandInterpreter &interpreter, 6428a5e2969SGongyu Deng CompletionRequest &request, 6438a5e2969SGongyu Deng SearchFilter *searcher) { 6448a5e2969SGongyu Deng // Currently the only valid options for disassemble -F are default, and for 6458a5e2969SGongyu Deng // Intel architectures, att and intel. 6468a5e2969SGongyu Deng static const char *flavors[] = {"default", "att", "intel"}; 6478a5e2969SGongyu Deng for (const char *flavor : flavors) { 6488a5e2969SGongyu Deng request.TryCompleteCurrentArg(flavor); 6498a5e2969SGongyu Deng } 6508a5e2969SGongyu Deng } 6513ce57e01SGongyu Deng 6523ce57e01SGongyu Deng void CommandCompletions::TypeLanguages(CommandInterpreter &interpreter, 6533ce57e01SGongyu Deng CompletionRequest &request, 6543ce57e01SGongyu Deng SearchFilter *searcher) { 6553ce57e01SGongyu Deng for (int bit : 6563ce57e01SGongyu Deng Language::GetLanguagesSupportingTypeSystems().bitvector.set_bits()) { 6573ce57e01SGongyu Deng request.TryCompleteCurrentArg( 6583ce57e01SGongyu Deng Language::GetNameForLanguageType(static_cast<lldb::LanguageType>(bit))); 6593ce57e01SGongyu Deng } 6603ce57e01SGongyu Deng } 66166fa73faSGongyu Deng 66266fa73faSGongyu Deng void CommandCompletions::FrameIndexes(CommandInterpreter &interpreter, 66366fa73faSGongyu Deng CompletionRequest &request, 66466fa73faSGongyu Deng SearchFilter *searcher) { 66566fa73faSGongyu Deng const ExecutionContext &exe_ctx = interpreter.GetExecutionContext(); 66666fa73faSGongyu Deng if (!exe_ctx.HasProcessScope()) 66766fa73faSGongyu Deng return; 66866fa73faSGongyu Deng 66966fa73faSGongyu Deng lldb::ThreadSP thread_sp = exe_ctx.GetThreadSP(); 67066fa73faSGongyu Deng const uint32_t frame_num = thread_sp->GetStackFrameCount(); 67166fa73faSGongyu Deng for (uint32_t i = 0; i < frame_num; ++i) { 67266fa73faSGongyu Deng lldb::StackFrameSP frame_sp = thread_sp->GetStackFrameAtIndex(i); 67366fa73faSGongyu Deng StreamString strm; 67466fa73faSGongyu Deng frame_sp->Dump(&strm, false, true); 67566fa73faSGongyu Deng request.TryCompleteCurrentArg(std::to_string(i), strm.GetString()); 67666fa73faSGongyu Deng } 67766fa73faSGongyu Deng } 678b2b7dbb4SGongyu Deng 679b2b7dbb4SGongyu Deng void CommandCompletions::StopHookIDs(CommandInterpreter &interpreter, 680b2b7dbb4SGongyu Deng CompletionRequest &request, 681b2b7dbb4SGongyu Deng SearchFilter *searcher) { 682b2b7dbb4SGongyu Deng const lldb::TargetSP target_sp = 683b2b7dbb4SGongyu Deng interpreter.GetExecutionContext().GetTargetSP(); 684b2b7dbb4SGongyu Deng if (!target_sp) 685b2b7dbb4SGongyu Deng return; 686b2b7dbb4SGongyu Deng 687b2b7dbb4SGongyu Deng const size_t num = target_sp->GetNumStopHooks(); 688b2b7dbb4SGongyu Deng for (size_t idx = 0; idx < num; ++idx) { 689b2b7dbb4SGongyu Deng StreamString strm; 690b2b7dbb4SGongyu Deng // The value 11 is an offset to make the completion description looks 691b2b7dbb4SGongyu Deng // neater. 692b2b7dbb4SGongyu Deng strm.SetIndentLevel(11); 693b2b7dbb4SGongyu Deng const Target::StopHookSP stophook_sp = target_sp->GetStopHookAtIndex(idx); 694b2b7dbb4SGongyu Deng stophook_sp->GetDescription(&strm, lldb::eDescriptionLevelInitial); 695b2b7dbb4SGongyu Deng request.TryCompleteCurrentArg(std::to_string(stophook_sp->GetID()), 696b2b7dbb4SGongyu Deng strm.GetString()); 697b2b7dbb4SGongyu Deng } 698b2b7dbb4SGongyu Deng } 699a952fe23SGongyu Deng 700a952fe23SGongyu Deng void CommandCompletions::ThreadIndexes(CommandInterpreter &interpreter, 701a952fe23SGongyu Deng CompletionRequest &request, 702a952fe23SGongyu Deng SearchFilter *searcher) { 703a952fe23SGongyu Deng const ExecutionContext &exe_ctx = interpreter.GetExecutionContext(); 704a952fe23SGongyu Deng if (!exe_ctx.HasProcessScope()) 705a952fe23SGongyu Deng return; 706a952fe23SGongyu Deng 707a952fe23SGongyu Deng ThreadList &threads = exe_ctx.GetProcessPtr()->GetThreadList(); 708a952fe23SGongyu Deng lldb::ThreadSP thread_sp; 709a952fe23SGongyu Deng for (uint32_t idx = 0; (thread_sp = threads.GetThreadAtIndex(idx)); ++idx) { 710a952fe23SGongyu Deng StreamString strm; 711a952fe23SGongyu Deng thread_sp->GetStatus(strm, 0, 1, 1, true); 712a952fe23SGongyu Deng request.TryCompleteCurrentArg(std::to_string(thread_sp->GetIndexID()), 713a952fe23SGongyu Deng strm.GetString()); 714a952fe23SGongyu Deng } 715a952fe23SGongyu Deng } 7164f3559dbSGongyu Deng 7174f3559dbSGongyu Deng void CommandCompletions::WatchPointIDs(CommandInterpreter &interpreter, 7184f3559dbSGongyu Deng CompletionRequest &request, 7194f3559dbSGongyu Deng SearchFilter *searcher) { 7204f3559dbSGongyu Deng const ExecutionContext &exe_ctx = interpreter.GetExecutionContext(); 7214f3559dbSGongyu Deng if (!exe_ctx.HasTargetScope()) 7224f3559dbSGongyu Deng return; 7234f3559dbSGongyu Deng 7244f3559dbSGongyu Deng const WatchpointList &wp_list = exe_ctx.GetTargetPtr()->GetWatchpointList(); 7254f3559dbSGongyu Deng const size_t wp_num = wp_list.GetSize(); 7264f3559dbSGongyu Deng for (size_t idx = 0; idx < wp_num; ++idx) { 7274f3559dbSGongyu Deng const lldb::WatchpointSP wp_sp = wp_list.GetByIndex(idx); 7284f3559dbSGongyu Deng StreamString strm; 7294f3559dbSGongyu Deng wp_sp->Dump(&strm); 7304f3559dbSGongyu Deng request.TryCompleteCurrentArg(std::to_string(wp_sp->GetID()), 7314f3559dbSGongyu Deng strm.GetString()); 7324f3559dbSGongyu Deng } 7334f3559dbSGongyu Deng } 734