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" 16188f1ac3SGongyu Deng #include "lldb/DataFormatters/DataVisualization.h" 17190fadcdSZachary Turner #include "lldb/Host/FileSystem.h" 189b62fd2fSGreg Clayton #include "lldb/Interpreter/CommandCompletions.h" 199b62fd2fSGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h" 20c5011aedSJim Ingham #include "lldb/Interpreter/CommandObject.h" 21c5011aedSJim Ingham #include "lldb/Interpreter/CommandObjectMultiword.h" 22633a29cfSZachary Turner #include "lldb/Interpreter/OptionValueProperties.h" 231f746071SGreg Clayton #include "lldb/Symbol/CompileUnit.h" 24f21feadcSGreg Clayton #include "lldb/Symbol/Variable.h" 253ce57e01SGongyu Deng #include "lldb/Target/Language.h" 26a952fe23SGongyu Deng #include "lldb/Target/Process.h" 27a14f4a75SGongyu Deng #include "lldb/Target/RegisterContext.h" 2866fa73faSGongyu Deng #include "lldb/Target/Thread.h" 295713a05bSZachary Turner #include "lldb/Utility/FileSpec.h" 302f3df613SZachary Turner #include "lldb/Utility/StreamString.h" 312cc5a18dSZachary Turner #include "lldb/Utility/TildeExpressionResolver.h" 32c9af18a5SGreg Clayton 337d86ee5aSZachary Turner #include "llvm/Support/FileSystem.h" 342cc5a18dSZachary Turner #include "llvm/Support/Path.h" 35190fadcdSZachary Turner 36c9af18a5SGreg Clayton using namespace lldb_private; 37c9af18a5SGreg Clayton 38440460f1SRaphael Isemann // This is the command completion callback that is used to complete the 39440460f1SRaphael Isemann // argument of the option it is bound to (in the OptionDefinition table 40440460f1SRaphael Isemann // below). 41440460f1SRaphael Isemann typedef void (*CompletionCallback)(CommandInterpreter &interpreter, 42440460f1SRaphael Isemann CompletionRequest &request, 43440460f1SRaphael Isemann // A search filter to limit the search... 44440460f1SRaphael Isemann lldb_private::SearchFilter *searcher); 45440460f1SRaphael Isemann 46440460f1SRaphael Isemann struct CommonCompletionElement { 47440460f1SRaphael Isemann uint32_t type; 48440460f1SRaphael Isemann CompletionCallback callback; 49440460f1SRaphael Isemann }; 50440460f1SRaphael Isemann 51440460f1SRaphael Isemann bool CommandCompletions::InvokeCommonCompletionCallbacks( 52440460f1SRaphael Isemann CommandInterpreter &interpreter, uint32_t completion_mask, 53440460f1SRaphael Isemann CompletionRequest &request, SearchFilter *searcher) { 54440460f1SRaphael Isemann bool handled = false; 55440460f1SRaphael Isemann 56440460f1SRaphael Isemann const CommonCompletionElement common_completions[] = { 57c9af18a5SGreg Clayton {eSourceFileCompletion, CommandCompletions::SourceFiles}, 58558ce124SJim Ingham {eDiskFileCompletion, CommandCompletions::DiskFiles}, 59558ce124SJim Ingham {eDiskDirectoryCompletion, CommandCompletions::DiskDirectories}, 60c9af18a5SGreg Clayton {eSymbolCompletion, CommandCompletions::Symbols}, 61c9af18a5SGreg Clayton {eModuleCompletion, CommandCompletions::Modules}, 62419f1be7SGongyu Deng {eModuleUUIDCompletion, CommandCompletions::ModuleUUIDs}, 633df9a8dfSCaroline Tice {eSettingsNameCompletion, CommandCompletions::SettingsNames}, 64ab65b34fSGreg Clayton {ePlatformPluginCompletion, CommandCompletions::PlatformPluginNames}, 65ab65b34fSGreg Clayton {eArchitectureCompletion, CommandCompletions::ArchitectureNames}, 66f21feadcSGreg Clayton {eVariablePathCompletion, CommandCompletions::VariablePath}, 67a14f4a75SGongyu Deng {eRegisterCompletion, CommandCompletions::Registers}, 680e50b9a4SGongyu Deng {eBreakpointCompletion, CommandCompletions::Breakpoints}, 69763bc230SGongyu Deng {eProcessPluginCompletion, CommandCompletions::ProcessPluginNames}, 708a5e2969SGongyu Deng {eDisassemblyFlavorCompletion, CommandCompletions::DisassemblyFlavors}, 713ce57e01SGongyu Deng {eTypeLanguageCompletion, CommandCompletions::TypeLanguages}, 7266fa73faSGongyu Deng {eFrameIndexCompletion, CommandCompletions::FrameIndexes}, 73b2b7dbb4SGongyu Deng {eStopHookIDCompletion, CommandCompletions::StopHookIDs}, 74a952fe23SGongyu Deng {eThreadIndexCompletion, CommandCompletions::ThreadIndexes}, 754f3559dbSGongyu Deng {eWatchPointIDCompletion, CommandCompletions::WatchPointIDs}, 7622e63cbaSGongyu Deng {eBreakpointNameCompletion, CommandCompletions::BreakpointNames}, 7719311f5cSGongyu Deng {eProcessIDCompletion, CommandCompletions::ProcessIDs}, 7819311f5cSGongyu Deng {eProcessNameCompletion, CommandCompletions::ProcessNames}, 793cd8d7b1SGongyu Deng {eRemoteDiskFileCompletion, CommandCompletions::RemoteDiskFiles}, 80188f1ac3SGongyu Deng {eRemoteDiskDirectoryCompletion, 81188f1ac3SGongyu Deng CommandCompletions::RemoteDiskDirectories}, 82188f1ac3SGongyu Deng {eTypeCategoryNameCompletion, CommandCompletions::TypeCategoryNames}, 83c8ecc2a9SEugene Zelenko {eNoCompletion, nullptr} // This one has to be last in the list. 84c9af18a5SGreg Clayton }; 85c9af18a5SGreg Clayton 86b9c1b51eSKate Stone for (int i = 0;; i++) { 87440460f1SRaphael Isemann if (common_completions[i].type == eNoCompletion) 88c9af18a5SGreg Clayton break; 89440460f1SRaphael Isemann else if ((common_completions[i].type & completion_mask) == 90440460f1SRaphael Isemann common_completions[i].type && 91440460f1SRaphael Isemann common_completions[i].callback != nullptr) { 92c9af18a5SGreg Clayton handled = true; 93440460f1SRaphael Isemann common_completions[i].callback(interpreter, request, searcher); 94c9af18a5SGreg Clayton } 95c9af18a5SGreg Clayton } 96c9af18a5SGreg Clayton return handled; 97c9af18a5SGreg Clayton } 98c9af18a5SGreg Clayton 99572fc897SRaphael Isemann namespace { 100572fc897SRaphael Isemann // The Completer class is a convenient base class for building searchers that 101572fc897SRaphael Isemann // go along with the SearchFilter passed to the standard Completer functions. 102572fc897SRaphael Isemann class Completer : public Searcher { 103572fc897SRaphael Isemann public: 104572fc897SRaphael Isemann Completer(CommandInterpreter &interpreter, CompletionRequest &request) 105572fc897SRaphael Isemann : m_interpreter(interpreter), m_request(request) {} 106572fc897SRaphael Isemann 107572fc897SRaphael Isemann ~Completer() override = default; 108572fc897SRaphael Isemann 109572fc897SRaphael Isemann CallbackReturn SearchCallback(SearchFilter &filter, SymbolContext &context, 110572fc897SRaphael Isemann Address *addr) override = 0; 111572fc897SRaphael Isemann 112572fc897SRaphael Isemann lldb::SearchDepth GetDepth() override = 0; 113572fc897SRaphael Isemann 114572fc897SRaphael Isemann virtual void DoCompletion(SearchFilter *filter) = 0; 115572fc897SRaphael Isemann 116572fc897SRaphael Isemann protected: 117572fc897SRaphael Isemann CommandInterpreter &m_interpreter; 118572fc897SRaphael Isemann CompletionRequest &m_request; 119572fc897SRaphael Isemann 120572fc897SRaphael Isemann private: 121eaebcbc6SKonrad Kleine Completer(const Completer &) = delete; 122eaebcbc6SKonrad Kleine const Completer &operator=(const Completer &) = delete; 123572fc897SRaphael Isemann }; 124572fc897SRaphael Isemann } // namespace 125572fc897SRaphael Isemann 126572fc897SRaphael Isemann // SourceFileCompleter implements the source file completer 127572fc897SRaphael Isemann namespace { 128572fc897SRaphael Isemann class SourceFileCompleter : public Completer { 129572fc897SRaphael Isemann public: 130572fc897SRaphael Isemann SourceFileCompleter(CommandInterpreter &interpreter, 131572fc897SRaphael Isemann CompletionRequest &request) 132572fc897SRaphael Isemann : Completer(interpreter, request), m_matching_files() { 133572fc897SRaphael Isemann FileSpec partial_spec(m_request.GetCursorArgumentPrefix()); 134572fc897SRaphael Isemann m_file_name = partial_spec.GetFilename().GetCString(); 135572fc897SRaphael Isemann m_dir_name = partial_spec.GetDirectory().GetCString(); 136572fc897SRaphael Isemann } 137572fc897SRaphael Isemann 138572fc897SRaphael Isemann lldb::SearchDepth GetDepth() override { return lldb::eSearchDepthCompUnit; } 139572fc897SRaphael Isemann 140572fc897SRaphael Isemann Searcher::CallbackReturn SearchCallback(SearchFilter &filter, 141572fc897SRaphael Isemann SymbolContext &context, 142572fc897SRaphael Isemann Address *addr) override { 143572fc897SRaphael Isemann if (context.comp_unit != nullptr) { 144572fc897SRaphael Isemann const char *cur_file_name = 145572fc897SRaphael Isemann context.comp_unit->GetPrimaryFile().GetFilename().GetCString(); 146572fc897SRaphael Isemann const char *cur_dir_name = 147572fc897SRaphael Isemann context.comp_unit->GetPrimaryFile().GetDirectory().GetCString(); 148572fc897SRaphael Isemann 149572fc897SRaphael Isemann bool match = false; 150572fc897SRaphael Isemann if (m_file_name && cur_file_name && 151572fc897SRaphael Isemann strstr(cur_file_name, m_file_name) == cur_file_name) 152572fc897SRaphael Isemann match = true; 153572fc897SRaphael Isemann 154572fc897SRaphael Isemann if (match && m_dir_name && cur_dir_name && 155572fc897SRaphael Isemann strstr(cur_dir_name, m_dir_name) != cur_dir_name) 156572fc897SRaphael Isemann match = false; 157572fc897SRaphael Isemann 158572fc897SRaphael Isemann if (match) { 159572fc897SRaphael Isemann m_matching_files.AppendIfUnique(context.comp_unit->GetPrimaryFile()); 160572fc897SRaphael Isemann } 161572fc897SRaphael Isemann } 162572fc897SRaphael Isemann return Searcher::eCallbackReturnContinue; 163572fc897SRaphael Isemann } 164572fc897SRaphael Isemann 165572fc897SRaphael Isemann void DoCompletion(SearchFilter *filter) override { 166572fc897SRaphael Isemann filter->Search(*this); 167572fc897SRaphael Isemann // Now convert the filelist to completions: 168572fc897SRaphael Isemann for (size_t i = 0; i < m_matching_files.GetSize(); i++) { 169572fc897SRaphael Isemann m_request.AddCompletion( 170572fc897SRaphael Isemann m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString()); 171572fc897SRaphael Isemann } 172572fc897SRaphael Isemann } 173572fc897SRaphael Isemann 174572fc897SRaphael Isemann private: 175572fc897SRaphael Isemann FileSpecList m_matching_files; 176572fc897SRaphael Isemann const char *m_file_name; 177572fc897SRaphael Isemann const char *m_dir_name; 178572fc897SRaphael Isemann 179eaebcbc6SKonrad Kleine SourceFileCompleter(const SourceFileCompleter &) = delete; 180eaebcbc6SKonrad Kleine const SourceFileCompleter &operator=(const SourceFileCompleter &) = delete; 181572fc897SRaphael Isemann }; 182572fc897SRaphael Isemann } // namespace 183572fc897SRaphael Isemann 184572fc897SRaphael Isemann static bool regex_chars(const char comp) { 185572fc897SRaphael Isemann return llvm::StringRef("[](){}+.*|^$\\?").contains(comp); 186572fc897SRaphael Isemann } 187572fc897SRaphael Isemann 188572fc897SRaphael Isemann namespace { 189572fc897SRaphael Isemann class SymbolCompleter : public Completer { 190572fc897SRaphael Isemann 191572fc897SRaphael Isemann public: 192572fc897SRaphael Isemann SymbolCompleter(CommandInterpreter &interpreter, CompletionRequest &request) 193572fc897SRaphael Isemann : Completer(interpreter, request) { 194572fc897SRaphael Isemann std::string regex_str; 195572fc897SRaphael Isemann if (!m_request.GetCursorArgumentPrefix().empty()) { 196572fc897SRaphael Isemann regex_str.append("^"); 197572fc897SRaphael Isemann regex_str.append(std::string(m_request.GetCursorArgumentPrefix())); 198572fc897SRaphael Isemann } else { 199572fc897SRaphael Isemann // Match anything since the completion string is empty 200572fc897SRaphael Isemann regex_str.append("."); 201572fc897SRaphael Isemann } 202572fc897SRaphael Isemann std::string::iterator pos = 203572fc897SRaphael Isemann find_if(regex_str.begin() + 1, regex_str.end(), regex_chars); 204572fc897SRaphael Isemann while (pos < regex_str.end()) { 205572fc897SRaphael Isemann pos = regex_str.insert(pos, '\\'); 206572fc897SRaphael Isemann pos = find_if(pos + 2, regex_str.end(), regex_chars); 207572fc897SRaphael Isemann } 208572fc897SRaphael Isemann m_regex = RegularExpression(regex_str); 209572fc897SRaphael Isemann } 210572fc897SRaphael Isemann 211572fc897SRaphael Isemann lldb::SearchDepth GetDepth() override { return lldb::eSearchDepthModule; } 212572fc897SRaphael Isemann 213572fc897SRaphael Isemann Searcher::CallbackReturn SearchCallback(SearchFilter &filter, 214572fc897SRaphael Isemann SymbolContext &context, 215572fc897SRaphael Isemann Address *addr) override { 216572fc897SRaphael Isemann if (context.module_sp) { 217572fc897SRaphael Isemann SymbolContextList sc_list; 218c020be17SJonas Devlieghere ModuleFunctionSearchOptions function_options; 219c020be17SJonas Devlieghere function_options.include_symbols = true; 220c020be17SJonas Devlieghere function_options.include_inlines = true; 221c020be17SJonas Devlieghere context.module_sp->FindFunctions(m_regex, function_options, sc_list); 222572fc897SRaphael Isemann 223572fc897SRaphael Isemann SymbolContext sc; 224572fc897SRaphael Isemann // Now add the functions & symbols to the list - only add if unique: 225572fc897SRaphael Isemann for (uint32_t i = 0; i < sc_list.GetSize(); i++) { 226572fc897SRaphael Isemann if (sc_list.GetContextAtIndex(i, sc)) { 227572fc897SRaphael Isemann ConstString func_name = sc.GetFunctionName(Mangled::ePreferDemangled); 228572fc897SRaphael Isemann // Ensure that the function name matches the regex. This is more than 229572fc897SRaphael Isemann // a sanity check. It is possible that the demangled function name 230572fc897SRaphael Isemann // does not start with the prefix, for example when it's in an 231572fc897SRaphael Isemann // anonymous namespace. 232572fc897SRaphael Isemann if (!func_name.IsEmpty() && m_regex.Execute(func_name.GetStringRef())) 233572fc897SRaphael Isemann m_match_set.insert(func_name); 234572fc897SRaphael Isemann } 235572fc897SRaphael Isemann } 236572fc897SRaphael Isemann } 237572fc897SRaphael Isemann return Searcher::eCallbackReturnContinue; 238572fc897SRaphael Isemann } 239572fc897SRaphael Isemann 240572fc897SRaphael Isemann void DoCompletion(SearchFilter *filter) override { 241572fc897SRaphael Isemann filter->Search(*this); 242572fc897SRaphael Isemann collection::iterator pos = m_match_set.begin(), end = m_match_set.end(); 243572fc897SRaphael Isemann for (pos = m_match_set.begin(); pos != end; pos++) 244572fc897SRaphael Isemann m_request.AddCompletion((*pos).GetCString()); 245572fc897SRaphael Isemann } 246572fc897SRaphael Isemann 247572fc897SRaphael Isemann private: 248572fc897SRaphael Isemann RegularExpression m_regex; 249572fc897SRaphael Isemann typedef std::set<ConstString> collection; 250572fc897SRaphael Isemann collection m_match_set; 251572fc897SRaphael Isemann 252eaebcbc6SKonrad Kleine SymbolCompleter(const SymbolCompleter &) = delete; 253eaebcbc6SKonrad Kleine const SymbolCompleter &operator=(const SymbolCompleter &) = delete; 254572fc897SRaphael Isemann }; 255572fc897SRaphael Isemann } // namespace 256572fc897SRaphael Isemann 257572fc897SRaphael Isemann namespace { 258572fc897SRaphael Isemann class ModuleCompleter : public Completer { 259572fc897SRaphael Isemann public: 260572fc897SRaphael Isemann ModuleCompleter(CommandInterpreter &interpreter, CompletionRequest &request) 261572fc897SRaphael Isemann : Completer(interpreter, request) { 262572fc897SRaphael Isemann FileSpec partial_spec(m_request.GetCursorArgumentPrefix()); 263572fc897SRaphael Isemann m_file_name = partial_spec.GetFilename().GetCString(); 264572fc897SRaphael Isemann m_dir_name = partial_spec.GetDirectory().GetCString(); 265572fc897SRaphael Isemann } 266572fc897SRaphael Isemann 267572fc897SRaphael Isemann lldb::SearchDepth GetDepth() override { return lldb::eSearchDepthModule; } 268572fc897SRaphael Isemann 269572fc897SRaphael Isemann Searcher::CallbackReturn SearchCallback(SearchFilter &filter, 270572fc897SRaphael Isemann SymbolContext &context, 271572fc897SRaphael Isemann Address *addr) override { 272572fc897SRaphael Isemann if (context.module_sp) { 273572fc897SRaphael Isemann const char *cur_file_name = 274572fc897SRaphael Isemann context.module_sp->GetFileSpec().GetFilename().GetCString(); 275572fc897SRaphael Isemann const char *cur_dir_name = 276572fc897SRaphael Isemann context.module_sp->GetFileSpec().GetDirectory().GetCString(); 277572fc897SRaphael Isemann 278572fc897SRaphael Isemann bool match = false; 279572fc897SRaphael Isemann if (m_file_name && cur_file_name && 280572fc897SRaphael Isemann strstr(cur_file_name, m_file_name) == cur_file_name) 281572fc897SRaphael Isemann match = true; 282572fc897SRaphael Isemann 283572fc897SRaphael Isemann if (match && m_dir_name && cur_dir_name && 284572fc897SRaphael Isemann strstr(cur_dir_name, m_dir_name) != cur_dir_name) 285572fc897SRaphael Isemann match = false; 286572fc897SRaphael Isemann 287572fc897SRaphael Isemann if (match) { 288572fc897SRaphael Isemann m_request.AddCompletion(cur_file_name); 289572fc897SRaphael Isemann } 290572fc897SRaphael Isemann } 291572fc897SRaphael Isemann return Searcher::eCallbackReturnContinue; 292572fc897SRaphael Isemann } 293572fc897SRaphael Isemann 294572fc897SRaphael Isemann void DoCompletion(SearchFilter *filter) override { filter->Search(*this); } 295572fc897SRaphael Isemann 296572fc897SRaphael Isemann private: 297572fc897SRaphael Isemann const char *m_file_name; 298572fc897SRaphael Isemann const char *m_dir_name; 299572fc897SRaphael Isemann 300eaebcbc6SKonrad Kleine ModuleCompleter(const ModuleCompleter &) = delete; 301eaebcbc6SKonrad Kleine const ModuleCompleter &operator=(const ModuleCompleter &) = delete; 302572fc897SRaphael Isemann }; 303572fc897SRaphael Isemann } // namespace 304572fc897SRaphael Isemann 305ae34ed2cSRaphael Isemann void CommandCompletions::SourceFiles(CommandInterpreter &interpreter, 306a2e76c0bSRaphael Isemann CompletionRequest &request, 307a2e76c0bSRaphael Isemann SearchFilter *searcher) { 30862174682SRaphael Isemann SourceFileCompleter completer(interpreter, request); 309c9af18a5SGreg Clayton 310b9c1b51eSKate Stone if (searcher == nullptr) { 3112976d00aSJim Ingham lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget(); 31233df7cd3SJim Ingham SearchFilterForUnconstrainedSearches null_searcher(target_sp); 313c9af18a5SGreg Clayton completer.DoCompletion(&null_searcher); 314b9c1b51eSKate Stone } else { 315c9af18a5SGreg Clayton completer.DoCompletion(searcher); 316c9af18a5SGreg Clayton } 317c9af18a5SGreg Clayton } 318c9af18a5SGreg Clayton 319ae34ed2cSRaphael Isemann static void DiskFilesOrDirectories(const llvm::Twine &partial_name, 3205edee822SRaphael Isemann bool only_directories, 3215edee822SRaphael Isemann CompletionRequest &request, 3222cc5a18dSZachary Turner TildeExpressionResolver &Resolver) { 3232cc5a18dSZachary Turner llvm::SmallString<256> CompletionBuffer; 3242cc5a18dSZachary Turner llvm::SmallString<256> Storage; 3252cc5a18dSZachary Turner partial_name.toVector(CompletionBuffer); 326b2f1fb29SVirgile Bello 3272cc5a18dSZachary Turner if (CompletionBuffer.size() >= PATH_MAX) 328ae34ed2cSRaphael Isemann return; 329b2f1fb29SVirgile Bello 3302cc5a18dSZachary Turner namespace path = llvm::sys::path; 331b2f1fb29SVirgile Bello 3322cc5a18dSZachary Turner llvm::StringRef SearchDir; 3332cc5a18dSZachary Turner llvm::StringRef PartialItem; 3342cc5a18dSZachary Turner 3352cc5a18dSZachary Turner if (CompletionBuffer.startswith("~")) { 3361def2579SDavid Blaikie llvm::StringRef Buffer = CompletionBuffer; 3375c5091fcSZachary Turner size_t FirstSep = 3385c5091fcSZachary Turner Buffer.find_if([](char c) { return path::is_separator(c); }); 3392cc5a18dSZachary Turner 3402cc5a18dSZachary Turner llvm::StringRef Username = Buffer.take_front(FirstSep); 3412cc5a18dSZachary Turner llvm::StringRef Remainder; 3422cc5a18dSZachary Turner if (FirstSep != llvm::StringRef::npos) 3432cc5a18dSZachary Turner Remainder = Buffer.drop_front(FirstSep + 1); 3442cc5a18dSZachary Turner 345b3f44ad9SStella Stamenova llvm::SmallString<256> Resolved; 3462cc5a18dSZachary Turner if (!Resolver.ResolveExact(Username, Resolved)) { 3472cc5a18dSZachary Turner // We couldn't resolve it as a full username. If there were no slashes 3482cc5a18dSZachary Turner // then this might be a partial username. We try to resolve it as such 3492cc5a18dSZachary Turner // but after that, we're done regardless of any matches. 3502cc5a18dSZachary Turner if (FirstSep == llvm::StringRef::npos) { 3512cc5a18dSZachary Turner llvm::StringSet<> MatchSet; 352a2e76c0bSRaphael Isemann Resolver.ResolvePartial(Username, MatchSet); 3532cc5a18dSZachary Turner for (const auto &S : MatchSet) { 3542cc5a18dSZachary Turner Resolved = S.getKey(); 3552cc5a18dSZachary Turner path::append(Resolved, path::get_separator()); 3565edee822SRaphael Isemann request.AddCompletion(Resolved, "", CompletionMode::Partial); 357b2f1fb29SVirgile Bello } 358b2f1fb29SVirgile Bello } 359ae34ed2cSRaphael Isemann return; 3602cc5a18dSZachary Turner } 3610734e6a5SZachary Turner 36205097246SAdrian Prantl // If there was no trailing slash, then we're done as soon as we resolve 36305097246SAdrian Prantl // the expression to the correct directory. Otherwise we need to continue 3642cc5a18dSZachary Turner // looking for matches within that directory. 3652cc5a18dSZachary Turner if (FirstSep == llvm::StringRef::npos) { 3662cc5a18dSZachary Turner // Make sure it ends with a separator. 3672cc5a18dSZachary Turner path::append(CompletionBuffer, path::get_separator()); 3685edee822SRaphael Isemann request.AddCompletion(CompletionBuffer, "", CompletionMode::Partial); 369ae34ed2cSRaphael Isemann return; 3702cc5a18dSZachary Turner } 3712cc5a18dSZachary Turner 3722cc5a18dSZachary Turner // We want to keep the form the user typed, so we special case this to 3732cc5a18dSZachary Turner // search in the fully resolved directory, but CompletionBuffer keeps the 3742cc5a18dSZachary Turner // unmodified form that the user typed. 3752cc5a18dSZachary Turner Storage = Resolved; 37688ec2e4eSPavel Labath llvm::StringRef RemainderDir = path::parent_path(Remainder); 3774621e0b0SRaphael Isemann if (!RemainderDir.empty()) { 3784621e0b0SRaphael Isemann // Append the remaining path to the resolved directory. 3794621e0b0SRaphael Isemann Storage.append(path::get_separator()); 3804621e0b0SRaphael Isemann Storage.append(RemainderDir); 3814621e0b0SRaphael Isemann } 38217843885SRaphael Isemann SearchDir = Storage; 3830734e6a5SZachary Turner } else { 3842cc5a18dSZachary Turner SearchDir = path::parent_path(CompletionBuffer); 3852cc5a18dSZachary Turner } 3862cc5a18dSZachary Turner 3872cc5a18dSZachary Turner size_t FullPrefixLen = CompletionBuffer.size(); 3882cc5a18dSZachary Turner 3892cc5a18dSZachary Turner PartialItem = path::filename(CompletionBuffer); 39078a10a7aSFrederic Riss 39178a10a7aSFrederic Riss // path::filename() will return "." when the passed path ends with a 39278a10a7aSFrederic Riss // directory separator. We have to filter those out, but only when the 39378a10a7aSFrederic Riss // "." doesn't come from the completion request itself. 39478a10a7aSFrederic Riss if (PartialItem == "." && path::is_separator(CompletionBuffer.back())) 3952cc5a18dSZachary Turner PartialItem = llvm::StringRef(); 3962cc5a18dSZachary Turner 397426d1379SZachary Turner if (SearchDir.empty()) { 398426d1379SZachary Turner llvm::sys::fs::current_path(Storage); 399426d1379SZachary Turner SearchDir = Storage; 400426d1379SZachary Turner } 4012cc5a18dSZachary Turner assert(!PartialItem.contains(path::get_separator())); 4022cc5a18dSZachary Turner 4032cc5a18dSZachary Turner // SearchDir now contains the directory to search in, and Prefix contains the 4042cc5a18dSZachary Turner // text we want to match against items in that directory. 4052cc5a18dSZachary Turner 406edaf2bccSJonas Devlieghere FileSystem &fs = FileSystem::Instance(); 4072cc5a18dSZachary Turner std::error_code EC; 408edaf2bccSJonas Devlieghere llvm::vfs::directory_iterator Iter = fs.DirBegin(SearchDir, EC); 409edaf2bccSJonas Devlieghere llvm::vfs::directory_iterator End; 4102cc5a18dSZachary Turner for (; Iter != End && !EC; Iter.increment(EC)) { 4112cc5a18dSZachary Turner auto &Entry = *Iter; 412edaf2bccSJonas Devlieghere llvm::ErrorOr<llvm::vfs::Status> Status = fs.GetStatus(Entry.path()); 413edaf2bccSJonas Devlieghere 414edaf2bccSJonas Devlieghere if (!Status) 415edaf2bccSJonas Devlieghere continue; 4162cc5a18dSZachary Turner 4172cc5a18dSZachary Turner auto Name = path::filename(Entry.path()); 4182cc5a18dSZachary Turner 4192cc5a18dSZachary Turner // Omit ".", ".." 4202cc5a18dSZachary Turner if (Name == "." || Name == ".." || !Name.startswith(PartialItem)) 4212cc5a18dSZachary Turner continue; 4222cc5a18dSZachary Turner 423edaf2bccSJonas Devlieghere bool is_dir = Status->isDirectory(); 4242cc5a18dSZachary Turner 4252cc5a18dSZachary Turner // If it's a symlink, then we treat it as a directory as long as the target 4262cc5a18dSZachary Turner // is a directory. 427edaf2bccSJonas Devlieghere if (Status->isSymlink()) { 428edaf2bccSJonas Devlieghere FileSpec symlink_filespec(Entry.path()); 429edaf2bccSJonas Devlieghere FileSpec resolved_filespec; 430edaf2bccSJonas Devlieghere auto error = fs.ResolveSymbolicLink(symlink_filespec, resolved_filespec); 431edaf2bccSJonas Devlieghere if (error.Success()) 432edaf2bccSJonas Devlieghere is_dir = fs.IsDirectory(symlink_filespec); 4332cc5a18dSZachary Turner } 434edaf2bccSJonas Devlieghere 4352cc5a18dSZachary Turner if (only_directories && !is_dir) 4362cc5a18dSZachary Turner continue; 4372cc5a18dSZachary Turner 4382cc5a18dSZachary Turner // Shrink it back down so that it just has the original prefix the user 4392cc5a18dSZachary Turner // typed and remove the part of the name which is common to the located 4402cc5a18dSZachary Turner // item and what the user typed. 4412cc5a18dSZachary Turner CompletionBuffer.resize(FullPrefixLen); 4422cc5a18dSZachary Turner Name = Name.drop_front(PartialItem.size()); 4432cc5a18dSZachary Turner CompletionBuffer.append(Name); 4442cc5a18dSZachary Turner 4452cc5a18dSZachary Turner if (is_dir) { 4462cc5a18dSZachary Turner path::append(CompletionBuffer, path::get_separator()); 4470734e6a5SZachary Turner } 4480734e6a5SZachary Turner 4495edee822SRaphael Isemann CompletionMode mode = 4505edee822SRaphael Isemann is_dir ? CompletionMode::Partial : CompletionMode::Normal; 4515edee822SRaphael Isemann request.AddCompletion(CompletionBuffer, "", mode); 452d5bd3a1eSZachary Turner } 453558ce124SJim Ingham } 454558ce124SJim Ingham 4555edee822SRaphael Isemann static void DiskFilesOrDirectories(const llvm::Twine &partial_name, 4565edee822SRaphael Isemann bool only_directories, StringList &matches, 4575edee822SRaphael Isemann TildeExpressionResolver &Resolver) { 4585edee822SRaphael Isemann CompletionResult result; 4595edee822SRaphael Isemann std::string partial_name_str = partial_name.str(); 4605edee822SRaphael Isemann CompletionRequest request(partial_name_str, partial_name_str.size(), result); 4615edee822SRaphael Isemann DiskFilesOrDirectories(partial_name, only_directories, request, Resolver); 4625edee822SRaphael Isemann result.GetMatches(matches); 4635edee822SRaphael Isemann } 4645edee822SRaphael Isemann 465ae34ed2cSRaphael Isemann static void DiskFilesOrDirectories(CompletionRequest &request, 4661a6d7ab5SRaphael Isemann bool only_directories) { 46772787ac6SJonas Devlieghere StandardTildeExpressionResolver resolver; 4681a6d7ab5SRaphael Isemann DiskFilesOrDirectories(request.GetCursorArgumentPrefix(), only_directories, 4695edee822SRaphael Isemann request, resolver); 4701a6d7ab5SRaphael Isemann } 4711a6d7ab5SRaphael Isemann 472ae34ed2cSRaphael Isemann void CommandCompletions::DiskFiles(CommandInterpreter &interpreter, 473a2e76c0bSRaphael Isemann CompletionRequest &request, 474a2e76c0bSRaphael Isemann SearchFilter *searcher) { 475ae34ed2cSRaphael Isemann DiskFilesOrDirectories(request, /*only_dirs*/ false); 4762cc5a18dSZachary Turner } 4772cc5a18dSZachary Turner 478ae34ed2cSRaphael Isemann void CommandCompletions::DiskFiles(const llvm::Twine &partial_file_name, 4792cc5a18dSZachary Turner StringList &matches, 4802cc5a18dSZachary Turner TildeExpressionResolver &Resolver) { 481ae34ed2cSRaphael Isemann DiskFilesOrDirectories(partial_file_name, false, matches, Resolver); 482558ce124SJim Ingham } 483558ce124SJim Ingham 484ae34ed2cSRaphael Isemann void CommandCompletions::DiskDirectories(CommandInterpreter &interpreter, 485a2e76c0bSRaphael Isemann CompletionRequest &request, 486a2e76c0bSRaphael Isemann SearchFilter *searcher) { 487ae34ed2cSRaphael Isemann DiskFilesOrDirectories(request, /*only_dirs*/ true); 4882cc5a18dSZachary Turner } 4892cc5a18dSZachary Turner 490ae34ed2cSRaphael Isemann void CommandCompletions::DiskDirectories(const llvm::Twine &partial_file_name, 4912cc5a18dSZachary Turner StringList &matches, 4922cc5a18dSZachary Turner TildeExpressionResolver &Resolver) { 493ae34ed2cSRaphael Isemann DiskFilesOrDirectories(partial_file_name, true, matches, Resolver); 494558ce124SJim Ingham } 495558ce124SJim Ingham 4963cd8d7b1SGongyu Deng void CommandCompletions::RemoteDiskFiles(CommandInterpreter &interpreter, 4973cd8d7b1SGongyu Deng CompletionRequest &request, 4983cd8d7b1SGongyu Deng SearchFilter *searcher) { 4993cd8d7b1SGongyu Deng lldb::PlatformSP platform_sp = 5003cd8d7b1SGongyu Deng interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform(); 5013cd8d7b1SGongyu Deng if (platform_sp) 5023cd8d7b1SGongyu Deng platform_sp->AutoCompleteDiskFileOrDirectory(request, false); 5033cd8d7b1SGongyu Deng } 5043cd8d7b1SGongyu Deng 5053cd8d7b1SGongyu Deng void CommandCompletions::RemoteDiskDirectories(CommandInterpreter &interpreter, 5063cd8d7b1SGongyu Deng CompletionRequest &request, 5073cd8d7b1SGongyu Deng SearchFilter *searcher) { 5083cd8d7b1SGongyu Deng lldb::PlatformSP platform_sp = 5093cd8d7b1SGongyu Deng interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform(); 5103cd8d7b1SGongyu Deng if (platform_sp) 5113cd8d7b1SGongyu Deng platform_sp->AutoCompleteDiskFileOrDirectory(request, true); 5123cd8d7b1SGongyu Deng } 5133cd8d7b1SGongyu Deng 514ae34ed2cSRaphael Isemann void CommandCompletions::Modules(CommandInterpreter &interpreter, 515a2e76c0bSRaphael Isemann CompletionRequest &request, 516a2e76c0bSRaphael Isemann SearchFilter *searcher) { 517a2e76c0bSRaphael Isemann ModuleCompleter completer(interpreter, request); 518c9af18a5SGreg Clayton 519b9c1b51eSKate Stone if (searcher == nullptr) { 5202976d00aSJim Ingham lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget(); 52133df7cd3SJim Ingham SearchFilterForUnconstrainedSearches null_searcher(target_sp); 522c9af18a5SGreg Clayton completer.DoCompletion(&null_searcher); 523b9c1b51eSKate Stone } else { 524c9af18a5SGreg Clayton completer.DoCompletion(searcher); 525c9af18a5SGreg Clayton } 526c9af18a5SGreg Clayton } 527c9af18a5SGreg Clayton 528419f1be7SGongyu Deng void CommandCompletions::ModuleUUIDs(CommandInterpreter &interpreter, 529419f1be7SGongyu Deng CompletionRequest &request, 530419f1be7SGongyu Deng SearchFilter *searcher) { 531419f1be7SGongyu Deng const ExecutionContext &exe_ctx = interpreter.GetExecutionContext(); 532419f1be7SGongyu Deng if (!exe_ctx.HasTargetScope()) 533419f1be7SGongyu Deng return; 534419f1be7SGongyu Deng 535419f1be7SGongyu Deng exe_ctx.GetTargetPtr()->GetImages().ForEach( 536419f1be7SGongyu Deng [&request](const lldb::ModuleSP &module) { 537419f1be7SGongyu Deng StreamString strm; 538419f1be7SGongyu Deng module->GetDescription(strm.AsRawOstream(), 539419f1be7SGongyu Deng lldb::eDescriptionLevelInitial); 540419f1be7SGongyu Deng request.TryCompleteCurrentArg(module->GetUUID().GetAsString(), 541419f1be7SGongyu Deng strm.GetString()); 542419f1be7SGongyu Deng return true; 543419f1be7SGongyu Deng }); 544419f1be7SGongyu Deng } 545419f1be7SGongyu Deng 546ae34ed2cSRaphael Isemann void CommandCompletions::Symbols(CommandInterpreter &interpreter, 547a2e76c0bSRaphael Isemann CompletionRequest &request, 548a2e76c0bSRaphael Isemann SearchFilter *searcher) { 549a2e76c0bSRaphael Isemann SymbolCompleter completer(interpreter, request); 550c9af18a5SGreg Clayton 551b9c1b51eSKate Stone if (searcher == nullptr) { 5522976d00aSJim Ingham lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget(); 55333df7cd3SJim Ingham SearchFilterForUnconstrainedSearches null_searcher(target_sp); 554c9af18a5SGreg Clayton completer.DoCompletion(&null_searcher); 555b9c1b51eSKate Stone } else { 556c9af18a5SGreg Clayton completer.DoCompletion(searcher); 557c9af18a5SGreg Clayton } 558c9af18a5SGreg Clayton } 559c9af18a5SGreg Clayton 560ae34ed2cSRaphael Isemann void CommandCompletions::SettingsNames(CommandInterpreter &interpreter, 561a2e76c0bSRaphael Isemann CompletionRequest &request, 562a2e76c0bSRaphael Isemann SearchFilter *searcher) { 56367cc0636SGreg Clayton // Cache the full setting name list 56467cc0636SGreg Clayton static StringList g_property_names; 565b9c1b51eSKate Stone if (g_property_names.GetSize() == 0) { 56667cc0636SGreg Clayton // Generate the full setting name list on demand 567b9c1b51eSKate Stone lldb::OptionValuePropertiesSP properties_sp( 568b9c1b51eSKate Stone interpreter.GetDebugger().GetValueProperties()); 569b9c1b51eSKate Stone if (properties_sp) { 57067cc0636SGreg Clayton StreamString strm; 571c8ecc2a9SEugene Zelenko properties_sp->DumpValue(nullptr, strm, OptionValue::eDumpOptionName); 572adcd0268SBenjamin Kramer const std::string &str = std::string(strm.GetString()); 57367cc0636SGreg Clayton g_property_names.SplitIntoLines(str.c_str(), str.size()); 57467cc0636SGreg Clayton } 57567cc0636SGreg Clayton } 5763df9a8dfSCaroline Tice 57793ca36d7SRaphael Isemann for (const std::string &s : g_property_names) 57893ca36d7SRaphael Isemann request.TryCompleteCurrentArg(s); 579b8639f5cSRaphael Isemann } 580b8639f5cSRaphael Isemann 581ae34ed2cSRaphael Isemann void CommandCompletions::PlatformPluginNames(CommandInterpreter &interpreter, 582a2e76c0bSRaphael Isemann CompletionRequest &request, 583a2e76c0bSRaphael Isemann SearchFilter *searcher) { 584ae34ed2cSRaphael Isemann PluginManager::AutoCompletePlatformName(request.GetCursorArgumentPrefix(), 585ae34ed2cSRaphael Isemann request); 586ab65b34fSGreg Clayton } 587ab65b34fSGreg Clayton 588ae34ed2cSRaphael Isemann void CommandCompletions::ArchitectureNames(CommandInterpreter &interpreter, 589a2e76c0bSRaphael Isemann CompletionRequest &request, 590a2e76c0bSRaphael Isemann SearchFilter *searcher) { 591ae34ed2cSRaphael Isemann ArchSpec::AutoComplete(request); 592ab65b34fSGreg Clayton } 593ab65b34fSGreg Clayton 594ae34ed2cSRaphael Isemann void CommandCompletions::VariablePath(CommandInterpreter &interpreter, 595a2e76c0bSRaphael Isemann CompletionRequest &request, 596a2e76c0bSRaphael Isemann SearchFilter *searcher) { 597ae34ed2cSRaphael Isemann Variable::AutoComplete(interpreter.GetExecutionContext(), request); 598f21feadcSGreg Clayton } 599a14f4a75SGongyu Deng 600a14f4a75SGongyu Deng void CommandCompletions::Registers(CommandInterpreter &interpreter, 601a14f4a75SGongyu Deng CompletionRequest &request, 602a14f4a75SGongyu Deng SearchFilter *searcher) { 603*0542d152SKazu Hirata std::string reg_prefix; 604a14f4a75SGongyu Deng if (request.GetCursorArgumentPrefix().startswith("$")) 605a14f4a75SGongyu Deng reg_prefix = "$"; 606a14f4a75SGongyu Deng 607a14f4a75SGongyu Deng RegisterContext *reg_ctx = 608a14f4a75SGongyu Deng interpreter.GetExecutionContext().GetRegisterContext(); 609a14f4a75SGongyu Deng const size_t reg_num = reg_ctx->GetRegisterCount(); 610a14f4a75SGongyu Deng for (size_t reg_idx = 0; reg_idx < reg_num; ++reg_idx) { 611a14f4a75SGongyu Deng const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_idx); 612a14f4a75SGongyu Deng request.TryCompleteCurrentArg(reg_prefix + reg_info->name, 613a14f4a75SGongyu Deng reg_info->alt_name); 614a14f4a75SGongyu Deng } 615a14f4a75SGongyu Deng } 6160e50b9a4SGongyu Deng 6170e50b9a4SGongyu Deng void CommandCompletions::Breakpoints(CommandInterpreter &interpreter, 6180e50b9a4SGongyu Deng CompletionRequest &request, 6190e50b9a4SGongyu Deng SearchFilter *searcher) { 6200e50b9a4SGongyu Deng lldb::TargetSP target = interpreter.GetDebugger().GetSelectedTarget(); 6210e50b9a4SGongyu Deng if (!target) 6220e50b9a4SGongyu Deng return; 6230e50b9a4SGongyu Deng 6240e50b9a4SGongyu Deng const BreakpointList &breakpoints = target->GetBreakpointList(); 6250e50b9a4SGongyu Deng 6260e50b9a4SGongyu Deng std::unique_lock<std::recursive_mutex> lock; 6270e50b9a4SGongyu Deng target->GetBreakpointList().GetListMutex(lock); 6280e50b9a4SGongyu Deng 6290e50b9a4SGongyu Deng size_t num_breakpoints = breakpoints.GetSize(); 6300e50b9a4SGongyu Deng if (num_breakpoints == 0) 6310e50b9a4SGongyu Deng return; 6320e50b9a4SGongyu Deng 6330e50b9a4SGongyu Deng for (size_t i = 0; i < num_breakpoints; ++i) { 6340e50b9a4SGongyu Deng lldb::BreakpointSP bp = breakpoints.GetBreakpointAtIndex(i); 6350e50b9a4SGongyu Deng 6360e50b9a4SGongyu Deng StreamString s; 6370e50b9a4SGongyu Deng bp->GetDescription(&s, lldb::eDescriptionLevelBrief); 6380e50b9a4SGongyu Deng llvm::StringRef bp_info = s.GetString(); 6390e50b9a4SGongyu Deng 6400e50b9a4SGongyu Deng const size_t colon_pos = bp_info.find_first_of(':'); 6410e50b9a4SGongyu Deng if (colon_pos != llvm::StringRef::npos) 6420e50b9a4SGongyu Deng bp_info = bp_info.drop_front(colon_pos + 2); 6430e50b9a4SGongyu Deng 6440e50b9a4SGongyu Deng request.TryCompleteCurrentArg(std::to_string(bp->GetID()), bp_info); 6450e50b9a4SGongyu Deng } 6460e50b9a4SGongyu Deng } 647763bc230SGongyu Deng 64822e63cbaSGongyu Deng void CommandCompletions::BreakpointNames(CommandInterpreter &interpreter, 64922e63cbaSGongyu Deng CompletionRequest &request, 65022e63cbaSGongyu Deng SearchFilter *searcher) { 65122e63cbaSGongyu Deng lldb::TargetSP target = interpreter.GetDebugger().GetSelectedTarget(); 65222e63cbaSGongyu Deng if (!target) 65322e63cbaSGongyu Deng return; 65422e63cbaSGongyu Deng 65522e63cbaSGongyu Deng std::vector<std::string> name_list; 65622e63cbaSGongyu Deng target->GetBreakpointNames(name_list); 65722e63cbaSGongyu Deng 65822e63cbaSGongyu Deng for (const std::string &name : name_list) 65922e63cbaSGongyu Deng request.TryCompleteCurrentArg(name); 66022e63cbaSGongyu Deng } 66122e63cbaSGongyu Deng 662763bc230SGongyu Deng void CommandCompletions::ProcessPluginNames(CommandInterpreter &interpreter, 663763bc230SGongyu Deng CompletionRequest &request, 664763bc230SGongyu Deng SearchFilter *searcher) { 665763bc230SGongyu Deng PluginManager::AutoCompleteProcessName(request.GetCursorArgumentPrefix(), 666763bc230SGongyu Deng request); 667763bc230SGongyu Deng } 6688a5e2969SGongyu Deng void CommandCompletions::DisassemblyFlavors(CommandInterpreter &interpreter, 6698a5e2969SGongyu Deng CompletionRequest &request, 6708a5e2969SGongyu Deng SearchFilter *searcher) { 6718a5e2969SGongyu Deng // Currently the only valid options for disassemble -F are default, and for 6728a5e2969SGongyu Deng // Intel architectures, att and intel. 6738a5e2969SGongyu Deng static const char *flavors[] = {"default", "att", "intel"}; 6748a5e2969SGongyu Deng for (const char *flavor : flavors) { 6758a5e2969SGongyu Deng request.TryCompleteCurrentArg(flavor); 6768a5e2969SGongyu Deng } 6778a5e2969SGongyu Deng } 6783ce57e01SGongyu Deng 67919311f5cSGongyu Deng void CommandCompletions::ProcessIDs(CommandInterpreter &interpreter, 68019311f5cSGongyu Deng CompletionRequest &request, 68119311f5cSGongyu Deng SearchFilter *searcher) { 68219311f5cSGongyu Deng lldb::PlatformSP platform_sp(interpreter.GetPlatform(true)); 68319311f5cSGongyu Deng if (!platform_sp) 68419311f5cSGongyu Deng return; 68519311f5cSGongyu Deng ProcessInstanceInfoList process_infos; 68619311f5cSGongyu Deng ProcessInstanceInfoMatch match_info; 68719311f5cSGongyu Deng platform_sp->FindProcesses(match_info, process_infos); 68819311f5cSGongyu Deng for (const ProcessInstanceInfo &info : process_infos) 68919311f5cSGongyu Deng request.TryCompleteCurrentArg(std::to_string(info.GetProcessID()), 69019311f5cSGongyu Deng info.GetNameAsStringRef()); 69119311f5cSGongyu Deng } 69219311f5cSGongyu Deng 69319311f5cSGongyu Deng void CommandCompletions::ProcessNames(CommandInterpreter &interpreter, 69419311f5cSGongyu Deng CompletionRequest &request, 69519311f5cSGongyu Deng SearchFilter *searcher) { 69619311f5cSGongyu Deng lldb::PlatformSP platform_sp(interpreter.GetPlatform(true)); 69719311f5cSGongyu Deng if (!platform_sp) 69819311f5cSGongyu Deng return; 69919311f5cSGongyu Deng ProcessInstanceInfoList process_infos; 70019311f5cSGongyu Deng ProcessInstanceInfoMatch match_info; 70119311f5cSGongyu Deng platform_sp->FindProcesses(match_info, process_infos); 70219311f5cSGongyu Deng for (const ProcessInstanceInfo &info : process_infos) 70319311f5cSGongyu Deng request.TryCompleteCurrentArg(info.GetNameAsStringRef()); 70419311f5cSGongyu Deng } 70519311f5cSGongyu Deng 7063ce57e01SGongyu Deng void CommandCompletions::TypeLanguages(CommandInterpreter &interpreter, 7073ce57e01SGongyu Deng CompletionRequest &request, 7083ce57e01SGongyu Deng SearchFilter *searcher) { 7093ce57e01SGongyu Deng for (int bit : 7103ce57e01SGongyu Deng Language::GetLanguagesSupportingTypeSystems().bitvector.set_bits()) { 7113ce57e01SGongyu Deng request.TryCompleteCurrentArg( 7123ce57e01SGongyu Deng Language::GetNameForLanguageType(static_cast<lldb::LanguageType>(bit))); 7133ce57e01SGongyu Deng } 7143ce57e01SGongyu Deng } 71566fa73faSGongyu Deng 71666fa73faSGongyu Deng void CommandCompletions::FrameIndexes(CommandInterpreter &interpreter, 71766fa73faSGongyu Deng CompletionRequest &request, 71866fa73faSGongyu Deng SearchFilter *searcher) { 71966fa73faSGongyu Deng const ExecutionContext &exe_ctx = interpreter.GetExecutionContext(); 72066fa73faSGongyu Deng if (!exe_ctx.HasProcessScope()) 72166fa73faSGongyu Deng return; 72266fa73faSGongyu Deng 72366fa73faSGongyu Deng lldb::ThreadSP thread_sp = exe_ctx.GetThreadSP(); 72466fa73faSGongyu Deng const uint32_t frame_num = thread_sp->GetStackFrameCount(); 72566fa73faSGongyu Deng for (uint32_t i = 0; i < frame_num; ++i) { 72666fa73faSGongyu Deng lldb::StackFrameSP frame_sp = thread_sp->GetStackFrameAtIndex(i); 72766fa73faSGongyu Deng StreamString strm; 72866fa73faSGongyu Deng frame_sp->Dump(&strm, false, true); 72966fa73faSGongyu Deng request.TryCompleteCurrentArg(std::to_string(i), strm.GetString()); 73066fa73faSGongyu Deng } 73166fa73faSGongyu Deng } 732b2b7dbb4SGongyu Deng 733b2b7dbb4SGongyu Deng void CommandCompletions::StopHookIDs(CommandInterpreter &interpreter, 734b2b7dbb4SGongyu Deng CompletionRequest &request, 735b2b7dbb4SGongyu Deng SearchFilter *searcher) { 736b2b7dbb4SGongyu Deng const lldb::TargetSP target_sp = 737b2b7dbb4SGongyu Deng interpreter.GetExecutionContext().GetTargetSP(); 738b2b7dbb4SGongyu Deng if (!target_sp) 739b2b7dbb4SGongyu Deng return; 740b2b7dbb4SGongyu Deng 741b2b7dbb4SGongyu Deng const size_t num = target_sp->GetNumStopHooks(); 742b2b7dbb4SGongyu Deng for (size_t idx = 0; idx < num; ++idx) { 743b2b7dbb4SGongyu Deng StreamString strm; 744b2b7dbb4SGongyu Deng // The value 11 is an offset to make the completion description looks 745b2b7dbb4SGongyu Deng // neater. 746b2b7dbb4SGongyu Deng strm.SetIndentLevel(11); 747b2b7dbb4SGongyu Deng const Target::StopHookSP stophook_sp = target_sp->GetStopHookAtIndex(idx); 748b2b7dbb4SGongyu Deng stophook_sp->GetDescription(&strm, lldb::eDescriptionLevelInitial); 749b2b7dbb4SGongyu Deng request.TryCompleteCurrentArg(std::to_string(stophook_sp->GetID()), 750b2b7dbb4SGongyu Deng strm.GetString()); 751b2b7dbb4SGongyu Deng } 752b2b7dbb4SGongyu Deng } 753a952fe23SGongyu Deng 754a952fe23SGongyu Deng void CommandCompletions::ThreadIndexes(CommandInterpreter &interpreter, 755a952fe23SGongyu Deng CompletionRequest &request, 756a952fe23SGongyu Deng SearchFilter *searcher) { 757a952fe23SGongyu Deng const ExecutionContext &exe_ctx = interpreter.GetExecutionContext(); 758a952fe23SGongyu Deng if (!exe_ctx.HasProcessScope()) 759a952fe23SGongyu Deng return; 760a952fe23SGongyu Deng 761a952fe23SGongyu Deng ThreadList &threads = exe_ctx.GetProcessPtr()->GetThreadList(); 762a952fe23SGongyu Deng lldb::ThreadSP thread_sp; 763a952fe23SGongyu Deng for (uint32_t idx = 0; (thread_sp = threads.GetThreadAtIndex(idx)); ++idx) { 764a952fe23SGongyu Deng StreamString strm; 765a952fe23SGongyu Deng thread_sp->GetStatus(strm, 0, 1, 1, true); 766a952fe23SGongyu Deng request.TryCompleteCurrentArg(std::to_string(thread_sp->GetIndexID()), 767a952fe23SGongyu Deng strm.GetString()); 768a952fe23SGongyu Deng } 769a952fe23SGongyu Deng } 7704f3559dbSGongyu Deng 7714f3559dbSGongyu Deng void CommandCompletions::WatchPointIDs(CommandInterpreter &interpreter, 7724f3559dbSGongyu Deng CompletionRequest &request, 7734f3559dbSGongyu Deng SearchFilter *searcher) { 7744f3559dbSGongyu Deng const ExecutionContext &exe_ctx = interpreter.GetExecutionContext(); 7754f3559dbSGongyu Deng if (!exe_ctx.HasTargetScope()) 7764f3559dbSGongyu Deng return; 7774f3559dbSGongyu Deng 7784f3559dbSGongyu Deng const WatchpointList &wp_list = exe_ctx.GetTargetPtr()->GetWatchpointList(); 7797b54b1cdSMichał Górny for (lldb::WatchpointSP wp_sp : wp_list.Watchpoints()) { 7804f3559dbSGongyu Deng StreamString strm; 7814f3559dbSGongyu Deng wp_sp->Dump(&strm); 7824f3559dbSGongyu Deng request.TryCompleteCurrentArg(std::to_string(wp_sp->GetID()), 7834f3559dbSGongyu Deng strm.GetString()); 7844f3559dbSGongyu Deng } 7854f3559dbSGongyu Deng } 786188f1ac3SGongyu Deng 787188f1ac3SGongyu Deng void CommandCompletions::TypeCategoryNames(CommandInterpreter &interpreter, 788188f1ac3SGongyu Deng CompletionRequest &request, 789188f1ac3SGongyu Deng SearchFilter *searcher) { 790188f1ac3SGongyu Deng DataVisualization::Categories::ForEach( 791188f1ac3SGongyu Deng [&request](const lldb::TypeCategoryImplSP &category_sp) { 792188f1ac3SGongyu Deng request.TryCompleteCurrentArg(category_sp->GetName(), 793188f1ac3SGongyu Deng category_sp->GetDescription()); 794188f1ac3SGongyu Deng return true; 795188f1ac3SGongyu Deng }); 796188f1ac3SGongyu Deng } 797c5011aedSJim Ingham 798c5011aedSJim Ingham void CommandCompletions::CompleteModifiableCmdPathArgs( 799c5011aedSJim Ingham CommandInterpreter &interpreter, CompletionRequest &request, 800c5011aedSJim Ingham OptionElementVector &opt_element_vector) { 801c5011aedSJim Ingham // The only arguments constitute a command path, however, there might be 802c5011aedSJim Ingham // options interspersed among the arguments, and we need to skip those. Do that 803c5011aedSJim Ingham // by copying the args vector, and just dropping all the option bits: 804c5011aedSJim Ingham Args args = request.GetParsedLine(); 805c5011aedSJim Ingham std::vector<size_t> to_delete; 806c5011aedSJim Ingham for (auto &elem : opt_element_vector) { 807c5011aedSJim Ingham to_delete.push_back(elem.opt_pos); 808c5011aedSJim Ingham if (elem.opt_arg_pos != 0) 809c5011aedSJim Ingham to_delete.push_back(elem.opt_arg_pos); 810c5011aedSJim Ingham } 811c5011aedSJim Ingham sort(to_delete.begin(), to_delete.end(), std::greater<size_t>()); 812c5011aedSJim Ingham for (size_t idx : to_delete) 813c5011aedSJim Ingham args.DeleteArgumentAtIndex(idx); 814c5011aedSJim Ingham 815c5011aedSJim Ingham // At this point, we should only have args, so now lookup the command up to 816c5011aedSJim Ingham // the cursor element. 817c5011aedSJim Ingham 818c5011aedSJim Ingham // There's nothing here but options. It doesn't seem very useful here to 819c5011aedSJim Ingham // dump all the commands, so just return. 820c5011aedSJim Ingham size_t num_args = args.GetArgumentCount(); 821c5011aedSJim Ingham if (num_args == 0) 822c5011aedSJim Ingham return; 823c5011aedSJim Ingham 824c5011aedSJim Ingham // There's just one argument, so we should complete its name: 825c5011aedSJim Ingham StringList matches; 826c5011aedSJim Ingham if (num_args == 1) { 827c5011aedSJim Ingham interpreter.GetUserCommandObject(args.GetArgumentAtIndex(0), &matches, 828c5011aedSJim Ingham nullptr); 829c5011aedSJim Ingham request.AddCompletions(matches); 830c5011aedSJim Ingham return; 831c5011aedSJim Ingham } 832c5011aedSJim Ingham 833c5011aedSJim Ingham // There was more than one path element, lets find the containing command: 834c5011aedSJim Ingham Status error; 835c5011aedSJim Ingham CommandObjectMultiword *mwc = 836c5011aedSJim Ingham interpreter.VerifyUserMultiwordCmdPath(args, true, error); 837c5011aedSJim Ingham 838c5011aedSJim Ingham // Something was wrong somewhere along the path, but I don't think there's 839c5011aedSJim Ingham // a good way to go back and fill in the missing elements: 840c5011aedSJim Ingham if (error.Fail()) 841c5011aedSJim Ingham return; 842c5011aedSJim Ingham 843c5011aedSJim Ingham // This should never happen. We already handled the case of one argument 844c5011aedSJim Ingham // above, and we can only get Success & nullptr back if there's a one-word 845c5011aedSJim Ingham // leaf. 846c5011aedSJim Ingham assert(mwc != nullptr); 847c5011aedSJim Ingham 848c5011aedSJim Ingham mwc->GetSubcommandObject(args.GetArgumentAtIndex(num_args - 1), &matches); 849c5011aedSJim Ingham if (matches.GetSize() == 0) 850c5011aedSJim Ingham return; 851c5011aedSJim Ingham 852c5011aedSJim Ingham request.AddCompletions(matches); 853c5011aedSJim Ingham } 854