1c9af18a5SGreg Clayton //===-- CommandCompletions.cpp ----------------------------------*- C++ -*-===// 2c9af18a5SGreg Clayton // 3c9af18a5SGreg Clayton // The LLVM Compiler Infrastructure 4c9af18a5SGreg Clayton // 5c9af18a5SGreg Clayton // This file is distributed under the University of Illinois Open Source 6c9af18a5SGreg Clayton // License. See LICENSE.TXT for details. 7c9af18a5SGreg Clayton // 8c9af18a5SGreg Clayton //===----------------------------------------------------------------------===// 9c9af18a5SGreg Clayton 10c9af18a5SGreg Clayton // C Includes 11558ce124SJim Ingham #include <sys/stat.h> 12fd18426eSGreg Clayton #if defined(__APPLE__) || defined(__linux__) 137cc478b9SJim Ingham #include <pwd.h> 14fd18426eSGreg Clayton #endif 15558ce124SJim Ingham 16c9af18a5SGreg Clayton // C++ Includes 17c9af18a5SGreg Clayton // Other libraries and framework includes 18c8ecc2a9SEugene Zelenko #include "llvm/ADT/SmallString.h" 19c8ecc2a9SEugene Zelenko 20c9af18a5SGreg Clayton // Project includes 219b62fd2fSGreg Clayton #include "lldb/Core/FileSpecList.h" 221f746071SGreg Clayton #include "lldb/Core/Module.h" 23190fadcdSZachary Turner #include "lldb/Core/PluginManager.h" 24190fadcdSZachary Turner #include "lldb/Host/FileSpec.h" 25190fadcdSZachary Turner #include "lldb/Host/FileSystem.h" 269b62fd2fSGreg Clayton #include "lldb/Interpreter/Args.h" 279b62fd2fSGreg Clayton #include "lldb/Interpreter/CommandCompletions.h" 289b62fd2fSGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h" 29633a29cfSZachary Turner #include "lldb/Interpreter/OptionValueProperties.h" 301f746071SGreg Clayton #include "lldb/Symbol/CompileUnit.h" 31f21feadcSGreg Clayton #include "lldb/Symbol/Variable.h" 329b62fd2fSGreg Clayton #include "lldb/Target/Target.h" 339b62fd2fSGreg Clayton #include "lldb/Utility/CleanUp.h" 34c9af18a5SGreg Clayton 35190fadcdSZachary Turner #include "llvm/ADT/SmallString.h" 36190fadcdSZachary Turner 37c9af18a5SGreg Clayton using namespace lldb_private; 38c9af18a5SGreg Clayton 39c9af18a5SGreg Clayton CommandCompletions::CommonCompletionElement 40*b9c1b51eSKate Stone CommandCompletions::g_common_completions[] = { 41c8ecc2a9SEugene Zelenko {eCustomCompletion, nullptr}, 42c9af18a5SGreg Clayton {eSourceFileCompletion, CommandCompletions::SourceFiles}, 43558ce124SJim Ingham {eDiskFileCompletion, CommandCompletions::DiskFiles}, 44558ce124SJim Ingham {eDiskDirectoryCompletion, CommandCompletions::DiskDirectories}, 45c9af18a5SGreg Clayton {eSymbolCompletion, CommandCompletions::Symbols}, 46c9af18a5SGreg Clayton {eModuleCompletion, CommandCompletions::Modules}, 473df9a8dfSCaroline Tice {eSettingsNameCompletion, CommandCompletions::SettingsNames}, 48ab65b34fSGreg Clayton {ePlatformPluginCompletion, CommandCompletions::PlatformPluginNames}, 49ab65b34fSGreg Clayton {eArchitectureCompletion, CommandCompletions::ArchitectureNames}, 50f21feadcSGreg Clayton {eVariablePathCompletion, CommandCompletions::VariablePath}, 51c8ecc2a9SEugene Zelenko {eNoCompletion, nullptr} // This one has to be last in the list. 52c9af18a5SGreg Clayton }; 53c9af18a5SGreg Clayton 54*b9c1b51eSKate Stone bool CommandCompletions::InvokeCommonCompletionCallbacks( 55*b9c1b51eSKate Stone CommandInterpreter &interpreter, uint32_t completion_mask, 56*b9c1b51eSKate Stone const char *completion_str, int match_start_point, int max_return_elements, 57*b9c1b51eSKate Stone SearchFilter *searcher, bool &word_complete, StringList &matches) { 58c9af18a5SGreg Clayton bool handled = false; 59c9af18a5SGreg Clayton 60c9af18a5SGreg Clayton if (completion_mask & eCustomCompletion) 61c9af18a5SGreg Clayton return false; 62c9af18a5SGreg Clayton 63*b9c1b51eSKate Stone for (int i = 0;; i++) { 64c9af18a5SGreg Clayton if (g_common_completions[i].type == eNoCompletion) 65c9af18a5SGreg Clayton break; 66*b9c1b51eSKate Stone else if ((g_common_completions[i].type & completion_mask) == 67*b9c1b51eSKate Stone g_common_completions[i].type && 68*b9c1b51eSKate Stone g_common_completions[i].callback != nullptr) { 69c9af18a5SGreg Clayton handled = true; 70*b9c1b51eSKate Stone g_common_completions[i].callback(interpreter, completion_str, 71*b9c1b51eSKate Stone match_start_point, max_return_elements, 72*b9c1b51eSKate Stone searcher, word_complete, matches); 73c9af18a5SGreg Clayton } 74c9af18a5SGreg Clayton } 75c9af18a5SGreg Clayton return handled; 76c9af18a5SGreg Clayton } 77c9af18a5SGreg Clayton 78*b9c1b51eSKate Stone int CommandCompletions::SourceFiles(CommandInterpreter &interpreter, 796611103cSGreg Clayton const char *partial_file_name, 80c9af18a5SGreg Clayton int match_start_point, 81c9af18a5SGreg Clayton int max_return_elements, 82*b9c1b51eSKate Stone SearchFilter *searcher, bool &word_complete, 83*b9c1b51eSKate Stone StringList &matches) { 84558ce124SJim Ingham word_complete = true; 85c9af18a5SGreg Clayton // Find some way to switch "include support files..." 86*b9c1b51eSKate Stone SourceFileCompleter completer(interpreter, false, partial_file_name, 87*b9c1b51eSKate Stone match_start_point, max_return_elements, 88c9af18a5SGreg Clayton matches); 89c9af18a5SGreg Clayton 90*b9c1b51eSKate Stone if (searcher == nullptr) { 912976d00aSJim Ingham lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget(); 9233df7cd3SJim Ingham SearchFilterForUnconstrainedSearches null_searcher(target_sp); 93c9af18a5SGreg Clayton completer.DoCompletion(&null_searcher); 94*b9c1b51eSKate Stone } else { 95c9af18a5SGreg Clayton completer.DoCompletion(searcher); 96c9af18a5SGreg Clayton } 97c9af18a5SGreg Clayton return matches.GetSize(); 98c9af18a5SGreg Clayton } 99c9af18a5SGreg Clayton 100*b9c1b51eSKate Stone typedef struct DiskFilesOrDirectoriesBaton { 101b2f1fb29SVirgile Bello const char *remainder; 102b2f1fb29SVirgile Bello char *partial_name_copy; 103b2f1fb29SVirgile Bello bool only_directories; 104b2f1fb29SVirgile Bello bool *saw_directory; 105b2f1fb29SVirgile Bello StringList *matches; 106b2f1fb29SVirgile Bello char *end_ptr; 107b2f1fb29SVirgile Bello size_t baselen; 1080b5e5f43SMichael Sartain } DiskFilesOrDirectoriesBaton; 109b2f1fb29SVirgile Bello 110*b9c1b51eSKate Stone FileSpec::EnumerateDirectoryResult 111*b9c1b51eSKate Stone DiskFilesOrDirectoriesCallback(void *baton, FileSpec::FileType file_type, 112*b9c1b51eSKate Stone const FileSpec &spec) { 113b2f1fb29SVirgile Bello const char *name = spec.GetFilename().AsCString(); 114b2f1fb29SVirgile Bello 115*b9c1b51eSKate Stone const DiskFilesOrDirectoriesBaton *parameters = 116*b9c1b51eSKate Stone (DiskFilesOrDirectoriesBaton *)baton; 117b2f1fb29SVirgile Bello char *end_ptr = parameters->end_ptr; 118b2f1fb29SVirgile Bello char *partial_name_copy = parameters->partial_name_copy; 119b2f1fb29SVirgile Bello const char *remainder = parameters->remainder; 120b2f1fb29SVirgile Bello 121b2f1fb29SVirgile Bello // Omit ".", ".." and any . files if the match string doesn't start with . 122*b9c1b51eSKate Stone if (name[0] == '.') { 123b2f1fb29SVirgile Bello if (name[1] == '\0') 124b2f1fb29SVirgile Bello return FileSpec::eEnumerateDirectoryResultNext; 125b2f1fb29SVirgile Bello else if (name[1] == '.' && name[2] == '\0') 126b2f1fb29SVirgile Bello return FileSpec::eEnumerateDirectoryResultNext; 127b2f1fb29SVirgile Bello else if (remainder[0] != '.') 128b2f1fb29SVirgile Bello return FileSpec::eEnumerateDirectoryResultNext; 129b2f1fb29SVirgile Bello } 130b2f1fb29SVirgile Bello 131b2f1fb29SVirgile Bello // If we found a directory, we put a "/" at the end of the name. 132b2f1fb29SVirgile Bello 133*b9c1b51eSKate Stone if (remainder[0] == '\0' || strstr(name, remainder) == name) { 134b2f1fb29SVirgile Bello if (strlen(name) + parameters->baselen >= PATH_MAX) 135b2f1fb29SVirgile Bello return FileSpec::eEnumerateDirectoryResultNext; 136b2f1fb29SVirgile Bello 137b2f1fb29SVirgile Bello strcpy(end_ptr, name); 138b2f1fb29SVirgile Bello 139b2f1fb29SVirgile Bello bool isa_directory = false; 140b2f1fb29SVirgile Bello if (file_type == FileSpec::eFileTypeDirectory) 141b2f1fb29SVirgile Bello isa_directory = true; 142*b9c1b51eSKate Stone else if (file_type == FileSpec::eFileTypeSymbolicLink) { 143190fadcdSZachary Turner if (FileSpec(partial_name_copy, false).IsDirectory()) 144b2f1fb29SVirgile Bello isa_directory = true; 145b2f1fb29SVirgile Bello } 146b2f1fb29SVirgile Bello 147*b9c1b51eSKate Stone if (isa_directory) { 148b2f1fb29SVirgile Bello *parameters->saw_directory = true; 149b2f1fb29SVirgile Bello size_t len = strlen(parameters->partial_name_copy); 150b2f1fb29SVirgile Bello partial_name_copy[len] = '/'; 151b2f1fb29SVirgile Bello partial_name_copy[len + 1] = '\0'; 152b2f1fb29SVirgile Bello } 153b2f1fb29SVirgile Bello if (parameters->only_directories && !isa_directory) 154b2f1fb29SVirgile Bello return FileSpec::eEnumerateDirectoryResultNext; 155b2f1fb29SVirgile Bello parameters->matches->AppendString(partial_name_copy); 156b2f1fb29SVirgile Bello } 157b2f1fb29SVirgile Bello 158b2f1fb29SVirgile Bello return FileSpec::eEnumerateDirectoryResultNext; 159b2f1fb29SVirgile Bello } 160b2f1fb29SVirgile Bello 161*b9c1b51eSKate Stone static int DiskFilesOrDirectories(const char *partial_file_name, 162*b9c1b51eSKate Stone bool only_directories, bool &saw_directory, 163*b9c1b51eSKate Stone StringList &matches) { 164*b9c1b51eSKate Stone // I'm going to use the "glob" function with GLOB_TILDE for user directory 165*b9c1b51eSKate Stone // expansion. 166*b9c1b51eSKate Stone // If it is not defined on your host system, you'll need to implement it 167*b9c1b51eSKate Stone // yourself... 168558ce124SJim Ingham 169c7bece56SGreg Clayton size_t partial_name_len = strlen(partial_file_name); 170558ce124SJim Ingham 171558ce124SJim Ingham if (partial_name_len >= PATH_MAX) 172558ce124SJim Ingham return matches.GetSize(); 173558ce124SJim Ingham 174*b9c1b51eSKate Stone // This copy of the string will be cut up into the directory part, and the 175*b9c1b51eSKate Stone // remainder. end_ptr 176*b9c1b51eSKate Stone // below will point to the place of the remainder in this string. Then when 177*b9c1b51eSKate Stone // we've resolved the 178*b9c1b51eSKate Stone // containing directory, and opened it, we'll read the directory contents and 179*b9c1b51eSKate Stone // overwrite the 180*b9c1b51eSKate Stone // partial_name_copy starting from end_ptr with each of the matches. Thus we 181*b9c1b51eSKate Stone // will preserve 182558ce124SJim Ingham // the form the user originally typed. 183558ce124SJim Ingham 184558ce124SJim Ingham char partial_name_copy[PATH_MAX]; 185021b605dSBenjamin Kramer memcpy(partial_name_copy, partial_file_name, partial_name_len); 186558ce124SJim Ingham partial_name_copy[partial_name_len] = '\0'; 187558ce124SJim Ingham 188*b9c1b51eSKate Stone // We'll need to save a copy of the remainder for comparison, which we do 189*b9c1b51eSKate Stone // here. 190558ce124SJim Ingham char remainder[PATH_MAX]; 191558ce124SJim Ingham 192*b9c1b51eSKate Stone // end_ptr will point past the last / in partial_name_copy, or if there is no 193*b9c1b51eSKate Stone // slash to the beginning of the string. 194558ce124SJim Ingham char *end_ptr; 195558ce124SJim Ingham 196558ce124SJim Ingham end_ptr = strrchr(partial_name_copy, '/'); 197558ce124SJim Ingham 198558ce124SJim Ingham // This will store the resolved form of the containing directory 1993f559740SZachary Turner llvm::SmallString<64> containing_part; 200558ce124SJim Ingham 201*b9c1b51eSKate Stone if (end_ptr == nullptr) { 202558ce124SJim Ingham // There's no directory. If the thing begins with a "~" then this is a bare 203558ce124SJim Ingham // user name. 204*b9c1b51eSKate Stone if (*partial_name_copy == '~') { 205558ce124SJim Ingham // Nothing here but the user name. We could just put a slash on the end, 206*b9c1b51eSKate Stone // but for completeness sake we'll resolve the user name and only put a 207*b9c1b51eSKate Stone // slash 208558ce124SJim Ingham // on the end if it exists. 2093f559740SZachary Turner llvm::SmallString<64> resolved_username(partial_name_copy); 2103f559740SZachary Turner FileSpec::ResolveUsername(resolved_username); 2117cc478b9SJim Ingham 212*b9c1b51eSKate Stone // Not sure how this would happen, a username longer than PATH_MAX? 213*b9c1b51eSKate Stone // Still... 214*b9c1b51eSKate Stone if (resolved_username.size() == 0) { 215*b9c1b51eSKate Stone // The user name didn't resolve, let's look in the password database for 216*b9c1b51eSKate Stone // matches. 217*b9c1b51eSKate Stone // The user name database contains duplicates, and is not in 218*b9c1b51eSKate Stone // alphabetical order, so 2197cc478b9SJim Ingham // we'll use a set to manage that for us. 22084363078SJim Ingham FileSpec::ResolvePartialUsername(partial_name_copy, matches); 22184363078SJim Ingham if (matches.GetSize() > 0) 2227cc478b9SJim Ingham saw_directory = true; 2237cc478b9SJim Ingham return matches.GetSize(); 224*b9c1b51eSKate Stone } else { 225558ce124SJim Ingham // The thing exists, put a '/' on the end, and return it... 226558ce124SJim Ingham // FIXME: complete user names here: 227558ce124SJim Ingham partial_name_copy[partial_name_len] = '/'; 228558ce124SJim Ingham partial_name_copy[partial_name_len + 1] = '\0'; 229558ce124SJim Ingham matches.AppendString(partial_name_copy); 230021b605dSBenjamin Kramer saw_directory = true; 231558ce124SJim Ingham return matches.GetSize(); 232558ce124SJim Ingham } 233*b9c1b51eSKate Stone } else { 234558ce124SJim Ingham // The containing part is the CWD, and the whole string is the remainder. 2353f559740SZachary Turner containing_part = "."; 236558ce124SJim Ingham strcpy(remainder, partial_name_copy); 237558ce124SJim Ingham end_ptr = partial_name_copy; 238558ce124SJim Ingham } 239*b9c1b51eSKate Stone } else { 240*b9c1b51eSKate Stone if (end_ptr == partial_name_copy) { 241558ce124SJim Ingham // We're completing a file or directory in the root volume. 2423f559740SZachary Turner containing_part = "/"; 243*b9c1b51eSKate Stone } else { 2443f559740SZachary Turner containing_part.append(partial_name_copy, end_ptr); 245558ce124SJim Ingham } 246558ce124SJim Ingham // Push end_ptr past the final "/" and set remainder. 247558ce124SJim Ingham end_ptr++; 248558ce124SJim Ingham strcpy(remainder, end_ptr); 249558ce124SJim Ingham } 250558ce124SJim Ingham 251*b9c1b51eSKate Stone // Look for a user name in the containing part, and if it's there, resolve it 252*b9c1b51eSKate Stone // and stick the 253558ce124SJim Ingham // result back into the containing_part: 254558ce124SJim Ingham 255*b9c1b51eSKate Stone if (*partial_name_copy == '~') { 2563f559740SZachary Turner FileSpec::ResolveUsername(containing_part); 257558ce124SJim Ingham // User name doesn't exist, we're not getting any further... 2583f559740SZachary Turner if (containing_part.empty()) 259558ce124SJim Ingham return matches.GetSize(); 260558ce124SJim Ingham } 261558ce124SJim Ingham 262*b9c1b51eSKate Stone // Okay, containing_part is now the directory we want to open and look for 263*b9c1b51eSKate Stone // files: 264558ce124SJim Ingham 265558ce124SJim Ingham size_t baselen = end_ptr - partial_name_copy; 266558ce124SJim Ingham 267b2f1fb29SVirgile Bello DiskFilesOrDirectoriesBaton parameters; 268b2f1fb29SVirgile Bello parameters.remainder = remainder; 269b2f1fb29SVirgile Bello parameters.partial_name_copy = partial_name_copy; 270b2f1fb29SVirgile Bello parameters.only_directories = only_directories; 271b2f1fb29SVirgile Bello parameters.saw_directory = &saw_directory; 272b2f1fb29SVirgile Bello parameters.matches = &matches; 273b2f1fb29SVirgile Bello parameters.end_ptr = end_ptr; 274b2f1fb29SVirgile Bello parameters.baselen = baselen; 275558ce124SJim Ingham 276*b9c1b51eSKate Stone FileSpec::EnumerateDirectory(containing_part.c_str(), true, true, true, 277*b9c1b51eSKate Stone DiskFilesOrDirectoriesCallback, ¶meters); 278558ce124SJim Ingham 279558ce124SJim Ingham return matches.GetSize(); 280558ce124SJim Ingham } 281558ce124SJim Ingham 282*b9c1b51eSKate Stone int CommandCompletions::DiskFiles(CommandInterpreter &interpreter, 283558ce124SJim Ingham const char *partial_file_name, 284558ce124SJim Ingham int match_start_point, 285558ce124SJim Ingham int max_return_elements, 286*b9c1b51eSKate Stone SearchFilter *searcher, bool &word_complete, 287*b9c1b51eSKate Stone StringList &matches) { 288*b9c1b51eSKate Stone int ret_val = 289*b9c1b51eSKate Stone DiskFilesOrDirectories(partial_file_name, false, word_complete, matches); 290558ce124SJim Ingham word_complete = !word_complete; 291558ce124SJim Ingham return ret_val; 292558ce124SJim Ingham } 293558ce124SJim Ingham 294*b9c1b51eSKate Stone int CommandCompletions::DiskDirectories( 295*b9c1b51eSKate Stone CommandInterpreter &interpreter, const char *partial_file_name, 296*b9c1b51eSKate Stone int match_start_point, int max_return_elements, SearchFilter *searcher, 297*b9c1b51eSKate Stone bool &word_complete, StringList &matches) { 298*b9c1b51eSKate Stone int ret_val = 299*b9c1b51eSKate Stone DiskFilesOrDirectories(partial_file_name, true, word_complete, matches); 300558ce124SJim Ingham word_complete = false; 301558ce124SJim Ingham return ret_val; 302558ce124SJim Ingham } 303558ce124SJim Ingham 304*b9c1b51eSKate Stone int CommandCompletions::Modules(CommandInterpreter &interpreter, 3056611103cSGreg Clayton const char *partial_file_name, 306*b9c1b51eSKate Stone int match_start_point, int max_return_elements, 307*b9c1b51eSKate Stone SearchFilter *searcher, bool &word_complete, 308*b9c1b51eSKate Stone StringList &matches) { 309558ce124SJim Ingham word_complete = true; 310*b9c1b51eSKate Stone ModuleCompleter completer(interpreter, partial_file_name, match_start_point, 311*b9c1b51eSKate Stone max_return_elements, matches); 312c9af18a5SGreg Clayton 313*b9c1b51eSKate Stone if (searcher == nullptr) { 3142976d00aSJim Ingham lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget(); 31533df7cd3SJim Ingham SearchFilterForUnconstrainedSearches null_searcher(target_sp); 316c9af18a5SGreg Clayton completer.DoCompletion(&null_searcher); 317*b9c1b51eSKate Stone } else { 318c9af18a5SGreg Clayton completer.DoCompletion(searcher); 319c9af18a5SGreg Clayton } 320c9af18a5SGreg Clayton return matches.GetSize(); 321c9af18a5SGreg Clayton } 322c9af18a5SGreg Clayton 323*b9c1b51eSKate Stone int CommandCompletions::Symbols(CommandInterpreter &interpreter, 3246611103cSGreg Clayton const char *partial_file_name, 325*b9c1b51eSKate Stone int match_start_point, int max_return_elements, 326*b9c1b51eSKate Stone SearchFilter *searcher, bool &word_complete, 327*b9c1b51eSKate Stone StringList &matches) { 328558ce124SJim Ingham word_complete = true; 329*b9c1b51eSKate Stone SymbolCompleter completer(interpreter, partial_file_name, match_start_point, 330*b9c1b51eSKate Stone max_return_elements, matches); 331c9af18a5SGreg Clayton 332*b9c1b51eSKate Stone if (searcher == nullptr) { 3332976d00aSJim Ingham lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget(); 33433df7cd3SJim Ingham SearchFilterForUnconstrainedSearches null_searcher(target_sp); 335c9af18a5SGreg Clayton completer.DoCompletion(&null_searcher); 336*b9c1b51eSKate Stone } else { 337c9af18a5SGreg Clayton completer.DoCompletion(searcher); 338c9af18a5SGreg Clayton } 339c9af18a5SGreg Clayton return matches.GetSize(); 340c9af18a5SGreg Clayton } 341c9af18a5SGreg Clayton 342*b9c1b51eSKate Stone int CommandCompletions::SettingsNames( 343*b9c1b51eSKate Stone CommandInterpreter &interpreter, const char *partial_setting_name, 344*b9c1b51eSKate Stone int match_start_point, int max_return_elements, SearchFilter *searcher, 345*b9c1b51eSKate Stone bool &word_complete, StringList &matches) { 34667cc0636SGreg Clayton // Cache the full setting name list 34767cc0636SGreg Clayton static StringList g_property_names; 348*b9c1b51eSKate Stone if (g_property_names.GetSize() == 0) { 34967cc0636SGreg Clayton // Generate the full setting name list on demand 350*b9c1b51eSKate Stone lldb::OptionValuePropertiesSP properties_sp( 351*b9c1b51eSKate Stone interpreter.GetDebugger().GetValueProperties()); 352*b9c1b51eSKate Stone if (properties_sp) { 35367cc0636SGreg Clayton StreamString strm; 354c8ecc2a9SEugene Zelenko properties_sp->DumpValue(nullptr, strm, OptionValue::eDumpOptionName); 35567cc0636SGreg Clayton const std::string &str = strm.GetString(); 35667cc0636SGreg Clayton g_property_names.SplitIntoLines(str.c_str(), str.size()); 35767cc0636SGreg Clayton } 35867cc0636SGreg Clayton } 3593df9a8dfSCaroline Tice 36067cc0636SGreg Clayton size_t exact_matches_idx = SIZE_MAX; 361*b9c1b51eSKate Stone const size_t num_matches = g_property_names.AutoComplete( 362*b9c1b51eSKate Stone partial_setting_name, matches, exact_matches_idx); 36367cc0636SGreg Clayton word_complete = exact_matches_idx != SIZE_MAX; 36467cc0636SGreg Clayton return num_matches; 3653df9a8dfSCaroline Tice } 3663df9a8dfSCaroline Tice 367*b9c1b51eSKate Stone int CommandCompletions::PlatformPluginNames( 368*b9c1b51eSKate Stone CommandInterpreter &interpreter, const char *partial_name, 369*b9c1b51eSKate Stone int match_start_point, int max_return_elements, SearchFilter *searcher, 370*b9c1b51eSKate Stone bool &word_complete, lldb_private::StringList &matches) { 371*b9c1b51eSKate Stone const uint32_t num_matches = 372*b9c1b51eSKate Stone PluginManager::AutoCompletePlatformName(partial_name, matches); 373ab65b34fSGreg Clayton word_complete = num_matches == 1; 374ab65b34fSGreg Clayton return num_matches; 375ab65b34fSGreg Clayton } 376ab65b34fSGreg Clayton 377*b9c1b51eSKate Stone int CommandCompletions::ArchitectureNames( 378*b9c1b51eSKate Stone CommandInterpreter &interpreter, const char *partial_name, 379*b9c1b51eSKate Stone int match_start_point, int max_return_elements, SearchFilter *searcher, 380*b9c1b51eSKate Stone bool &word_complete, lldb_private::StringList &matches) { 381ab65b34fSGreg Clayton const uint32_t num_matches = ArchSpec::AutoComplete(partial_name, matches); 382ab65b34fSGreg Clayton word_complete = num_matches == 1; 383ab65b34fSGreg Clayton return num_matches; 384ab65b34fSGreg Clayton } 385ab65b34fSGreg Clayton 386*b9c1b51eSKate Stone int CommandCompletions::VariablePath( 387*b9c1b51eSKate Stone CommandInterpreter &interpreter, const char *partial_name, 388*b9c1b51eSKate Stone int match_start_point, int max_return_elements, SearchFilter *searcher, 389*b9c1b51eSKate Stone bool &word_complete, lldb_private::StringList &matches) { 390*b9c1b51eSKate Stone return Variable::AutoComplete(interpreter.GetExecutionContext(), partial_name, 391*b9c1b51eSKate Stone matches, word_complete); 392f21feadcSGreg Clayton } 393f21feadcSGreg Clayton 394c8ecc2a9SEugene Zelenko CommandCompletions::Completer::Completer(CommandInterpreter &interpreter, 395c9af18a5SGreg Clayton const char *completion_str, 396c9af18a5SGreg Clayton int match_start_point, 397c9af18a5SGreg Clayton int max_return_elements, 398*b9c1b51eSKate Stone StringList &matches) 399*b9c1b51eSKate Stone : m_interpreter(interpreter), m_completion_str(completion_str), 400c9af18a5SGreg Clayton m_match_start_point(match_start_point), 401*b9c1b51eSKate Stone m_max_return_elements(max_return_elements), m_matches(matches) {} 402c9af18a5SGreg Clayton 403c8ecc2a9SEugene Zelenko CommandCompletions::Completer::~Completer() = default; 404c9af18a5SGreg Clayton 405c9af18a5SGreg Clayton //---------------------------------------------------------------------- 406c9af18a5SGreg Clayton // SourceFileCompleter 407c9af18a5SGreg Clayton //---------------------------------------------------------------------- 408c9af18a5SGreg Clayton 409*b9c1b51eSKate Stone CommandCompletions::SourceFileCompleter::SourceFileCompleter( 410*b9c1b51eSKate Stone CommandInterpreter &interpreter, bool include_support_files, 411*b9c1b51eSKate Stone const char *completion_str, int match_start_point, int max_return_elements, 412*b9c1b51eSKate Stone StringList &matches) 413*b9c1b51eSKate Stone : CommandCompletions::Completer(interpreter, completion_str, 414*b9c1b51eSKate Stone match_start_point, max_return_elements, 415*b9c1b51eSKate Stone matches), 416*b9c1b51eSKate Stone m_include_support_files(include_support_files), m_matching_files() { 417274060b6SGreg Clayton FileSpec partial_spec(m_completion_str.c_str(), false); 418c9af18a5SGreg Clayton m_file_name = partial_spec.GetFilename().GetCString(); 419c9af18a5SGreg Clayton m_dir_name = partial_spec.GetDirectory().GetCString(); 420c9af18a5SGreg Clayton } 421c9af18a5SGreg Clayton 422*b9c1b51eSKate Stone Searcher::Depth CommandCompletions::SourceFileCompleter::GetDepth() { 423c9af18a5SGreg Clayton return eDepthCompUnit; 424c9af18a5SGreg Clayton } 425c9af18a5SGreg Clayton 426c9af18a5SGreg Clayton Searcher::CallbackReturn 427c8ecc2a9SEugene Zelenko CommandCompletions::SourceFileCompleter::SearchCallback(SearchFilter &filter, 428c9af18a5SGreg Clayton SymbolContext &context, 429c9af18a5SGreg Clayton Address *addr, 430*b9c1b51eSKate Stone bool complete) { 431*b9c1b51eSKate Stone if (context.comp_unit != nullptr) { 432*b9c1b51eSKate Stone if (m_include_support_files) { 433c9af18a5SGreg Clayton FileSpecList supporting_files = context.comp_unit->GetSupportFiles(); 434*b9c1b51eSKate Stone for (size_t sfiles = 0; sfiles < supporting_files.GetSize(); sfiles++) { 435*b9c1b51eSKate Stone const FileSpec &sfile_spec = 436*b9c1b51eSKate Stone supporting_files.GetFileSpecAtIndex(sfiles); 437c9af18a5SGreg Clayton const char *sfile_file_name = sfile_spec.GetFilename().GetCString(); 438c9af18a5SGreg Clayton const char *sfile_dir_name = sfile_spec.GetFilename().GetCString(); 439c9af18a5SGreg Clayton bool match = false; 440*b9c1b51eSKate Stone if (m_file_name && sfile_file_name && 441*b9c1b51eSKate Stone strstr(sfile_file_name, m_file_name) == sfile_file_name) 442c9af18a5SGreg Clayton match = true; 443*b9c1b51eSKate Stone if (match && m_dir_name && sfile_dir_name && 444*b9c1b51eSKate Stone strstr(sfile_dir_name, m_dir_name) != sfile_dir_name) 445c9af18a5SGreg Clayton match = false; 446c9af18a5SGreg Clayton 447*b9c1b51eSKate Stone if (match) { 448c9af18a5SGreg Clayton m_matching_files.AppendIfUnique(sfile_spec); 449c9af18a5SGreg Clayton } 450c9af18a5SGreg Clayton } 451*b9c1b51eSKate Stone } else { 452c9af18a5SGreg Clayton const char *cur_file_name = context.comp_unit->GetFilename().GetCString(); 453c9af18a5SGreg Clayton const char *cur_dir_name = context.comp_unit->GetDirectory().GetCString(); 454c9af18a5SGreg Clayton 455c9af18a5SGreg Clayton bool match = false; 456*b9c1b51eSKate Stone if (m_file_name && cur_file_name && 457*b9c1b51eSKate Stone strstr(cur_file_name, m_file_name) == cur_file_name) 458c9af18a5SGreg Clayton match = true; 459c9af18a5SGreg Clayton 460*b9c1b51eSKate Stone if (match && m_dir_name && cur_dir_name && 461*b9c1b51eSKate Stone strstr(cur_dir_name, m_dir_name) != cur_dir_name) 462c9af18a5SGreg Clayton match = false; 463c9af18a5SGreg Clayton 464*b9c1b51eSKate Stone if (match) { 465c9af18a5SGreg Clayton m_matching_files.AppendIfUnique(context.comp_unit); 466c9af18a5SGreg Clayton } 467c9af18a5SGreg Clayton } 468c9af18a5SGreg Clayton } 469c9af18a5SGreg Clayton return Searcher::eCallbackReturnContinue; 470c9af18a5SGreg Clayton } 471c9af18a5SGreg Clayton 472c9af18a5SGreg Clayton size_t 473*b9c1b51eSKate Stone CommandCompletions::SourceFileCompleter::DoCompletion(SearchFilter *filter) { 474c9af18a5SGreg Clayton filter->Search(*this); 475c9af18a5SGreg Clayton // Now convert the filelist to completions: 476*b9c1b51eSKate Stone for (size_t i = 0; i < m_matching_files.GetSize(); i++) { 477*b9c1b51eSKate Stone m_matches.AppendString( 478*b9c1b51eSKate Stone m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString()); 479c9af18a5SGreg Clayton } 480c9af18a5SGreg Clayton return m_matches.GetSize(); 481c9af18a5SGreg Clayton } 482c9af18a5SGreg Clayton 483c9af18a5SGreg Clayton //---------------------------------------------------------------------- 484c9af18a5SGreg Clayton // SymbolCompleter 485c9af18a5SGreg Clayton //---------------------------------------------------------------------- 486c9af18a5SGreg Clayton 487*b9c1b51eSKate Stone static bool regex_chars(const char comp) { 488*b9c1b51eSKate Stone return (comp == '[' || comp == ']' || comp == '(' || comp == ')' || 489*b9c1b51eSKate Stone comp == '{' || comp == '}' || comp == '+' || comp == '.' || 490*b9c1b51eSKate Stone comp == '*' || comp == '|' || comp == '^' || comp == '$' || 491*b9c1b51eSKate Stone comp == '\\' || comp == '?'); 492c9af18a5SGreg Clayton } 493c8ecc2a9SEugene Zelenko 494*b9c1b51eSKate Stone CommandCompletions::SymbolCompleter::SymbolCompleter( 495*b9c1b51eSKate Stone CommandInterpreter &interpreter, const char *completion_str, 496*b9c1b51eSKate Stone int match_start_point, int max_return_elements, StringList &matches) 497*b9c1b51eSKate Stone : CommandCompletions::Completer(interpreter, completion_str, 498*b9c1b51eSKate Stone match_start_point, max_return_elements, 499*b9c1b51eSKate Stone matches) { 500649f8b9bSGreg Clayton std::string regex_str; 501*b9c1b51eSKate Stone if (completion_str && completion_str[0]) { 502649f8b9bSGreg Clayton regex_str.append("^"); 503c9af18a5SGreg Clayton regex_str.append(completion_str); 504*b9c1b51eSKate Stone } else { 505649f8b9bSGreg Clayton // Match anything since the completion string is empty 506649f8b9bSGreg Clayton regex_str.append("."); 507649f8b9bSGreg Clayton } 508*b9c1b51eSKate Stone std::string::iterator pos = 509*b9c1b51eSKate Stone find_if(regex_str.begin() + 1, regex_str.end(), regex_chars); 510*b9c1b51eSKate Stone while (pos < regex_str.end()) { 511c9af18a5SGreg Clayton pos = regex_str.insert(pos, '\\'); 512649f8b9bSGreg Clayton pos = find_if(pos + 2, regex_str.end(), regex_chars); 513c9af18a5SGreg Clayton } 514c9af18a5SGreg Clayton m_regex.Compile(regex_str.c_str()); 515c9af18a5SGreg Clayton } 516c9af18a5SGreg Clayton 517*b9c1b51eSKate Stone Searcher::Depth CommandCompletions::SymbolCompleter::GetDepth() { 518c9af18a5SGreg Clayton return eDepthModule; 519c9af18a5SGreg Clayton } 520c9af18a5SGreg Clayton 521*b9c1b51eSKate Stone Searcher::CallbackReturn CommandCompletions::SymbolCompleter::SearchCallback( 522*b9c1b51eSKate Stone SearchFilter &filter, SymbolContext &context, Address *addr, 523*b9c1b51eSKate Stone bool complete) { 524*b9c1b51eSKate Stone if (context.module_sp) { 525931180e6SGreg Clayton SymbolContextList sc_list; 526931180e6SGreg Clayton const bool include_symbols = true; 5279df05fbbSSean Callanan const bool include_inlines = true; 528931180e6SGreg Clayton const bool append = true; 529*b9c1b51eSKate Stone context.module_sp->FindFunctions(m_regex, include_symbols, include_inlines, 530*b9c1b51eSKate Stone append, sc_list); 531c9af18a5SGreg Clayton 532c9af18a5SGreg Clayton SymbolContext sc; 533c9af18a5SGreg Clayton // Now add the functions & symbols to the list - only add if unique: 534*b9c1b51eSKate Stone for (uint32_t i = 0; i < sc_list.GetSize(); i++) { 535*b9c1b51eSKate Stone if (sc_list.GetContextAtIndex(i, sc)) { 536530a413cSJim Ingham ConstString func_name = sc.GetFunctionName(Mangled::ePreferDemangled); 537530a413cSJim Ingham if (!func_name.IsEmpty()) 538530a413cSJim Ingham m_match_set.insert(func_name); 539c9af18a5SGreg Clayton } 540c9af18a5SGreg Clayton } 541c9af18a5SGreg Clayton } 542c9af18a5SGreg Clayton return Searcher::eCallbackReturnContinue; 543c9af18a5SGreg Clayton } 544c9af18a5SGreg Clayton 545*b9c1b51eSKate Stone size_t CommandCompletions::SymbolCompleter::DoCompletion(SearchFilter *filter) { 546c9af18a5SGreg Clayton filter->Search(*this); 547c9af18a5SGreg Clayton collection::iterator pos = m_match_set.begin(), end = m_match_set.end(); 548c9af18a5SGreg Clayton for (pos = m_match_set.begin(); pos != end; pos++) 549c9af18a5SGreg Clayton m_matches.AppendString((*pos).GetCString()); 550c9af18a5SGreg Clayton 551c9af18a5SGreg Clayton return m_matches.GetSize(); 552c9af18a5SGreg Clayton } 553c9af18a5SGreg Clayton 554c9af18a5SGreg Clayton //---------------------------------------------------------------------- 555c9af18a5SGreg Clayton // ModuleCompleter 556c9af18a5SGreg Clayton //---------------------------------------------------------------------- 557*b9c1b51eSKate Stone CommandCompletions::ModuleCompleter::ModuleCompleter( 558*b9c1b51eSKate Stone CommandInterpreter &interpreter, const char *completion_str, 559*b9c1b51eSKate Stone int match_start_point, int max_return_elements, StringList &matches) 560*b9c1b51eSKate Stone : CommandCompletions::Completer(interpreter, completion_str, 561*b9c1b51eSKate Stone match_start_point, max_return_elements, 562*b9c1b51eSKate Stone matches) { 563274060b6SGreg Clayton FileSpec partial_spec(m_completion_str.c_str(), false); 564c9af18a5SGreg Clayton m_file_name = partial_spec.GetFilename().GetCString(); 565c9af18a5SGreg Clayton m_dir_name = partial_spec.GetDirectory().GetCString(); 566c9af18a5SGreg Clayton } 567c9af18a5SGreg Clayton 568*b9c1b51eSKate Stone Searcher::Depth CommandCompletions::ModuleCompleter::GetDepth() { 569c9af18a5SGreg Clayton return eDepthModule; 570c9af18a5SGreg Clayton } 571c9af18a5SGreg Clayton 572*b9c1b51eSKate Stone Searcher::CallbackReturn CommandCompletions::ModuleCompleter::SearchCallback( 573*b9c1b51eSKate Stone SearchFilter &filter, SymbolContext &context, Address *addr, 574*b9c1b51eSKate Stone bool complete) { 575*b9c1b51eSKate Stone if (context.module_sp) { 576*b9c1b51eSKate Stone const char *cur_file_name = 577*b9c1b51eSKate Stone context.module_sp->GetFileSpec().GetFilename().GetCString(); 578*b9c1b51eSKate Stone const char *cur_dir_name = 579*b9c1b51eSKate Stone context.module_sp->GetFileSpec().GetDirectory().GetCString(); 580c9af18a5SGreg Clayton 581c9af18a5SGreg Clayton bool match = false; 582*b9c1b51eSKate Stone if (m_file_name && cur_file_name && 583*b9c1b51eSKate Stone strstr(cur_file_name, m_file_name) == cur_file_name) 584c9af18a5SGreg Clayton match = true; 585c9af18a5SGreg Clayton 586*b9c1b51eSKate Stone if (match && m_dir_name && cur_dir_name && 587*b9c1b51eSKate Stone strstr(cur_dir_name, m_dir_name) != cur_dir_name) 588c9af18a5SGreg Clayton match = false; 589c9af18a5SGreg Clayton 590*b9c1b51eSKate Stone if (match) { 591c9af18a5SGreg Clayton m_matches.AppendString(cur_file_name); 592c9af18a5SGreg Clayton } 593c9af18a5SGreg Clayton } 594c9af18a5SGreg Clayton return Searcher::eCallbackReturnContinue; 595c9af18a5SGreg Clayton } 596c9af18a5SGreg Clayton 597*b9c1b51eSKate Stone size_t CommandCompletions::ModuleCompleter::DoCompletion(SearchFilter *filter) { 598c9af18a5SGreg Clayton filter->Search(*this); 599c9af18a5SGreg Clayton return m_matches.GetSize(); 600c9af18a5SGreg Clayton } 601