LLDB mainline
CommandCompletions.cpp
Go to the documentation of this file.
1//===-- CommandCompletions.cpp --------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "llvm/ADT/STLExtras.h"
10#include "llvm/ADT/SmallString.h"
11#include "llvm/ADT/StringRef.h"
12#include "llvm/ADT/StringSet.h"
13
15#include "lldb/Core/Module.h"
28#include "lldb/Target/Process.h"
30#include "lldb/Target/Thread.h"
35
36#include "llvm/Support/FileSystem.h"
37#include "llvm/Support/Path.h"
38
39using namespace lldb_private;
40
41// This is the command completion callback that is used to complete the
42// argument of the option it is bound to (in the OptionDefinition table
43// below).
44typedef void (*CompletionCallback)(CommandInterpreter &interpreter,
45 CompletionRequest &request,
46 // A search filter to limit the search...
48
53
55 CommandInterpreter &interpreter, uint32_t completion_mask,
56 CompletionRequest &request, SearchFilter *searcher) {
57 bool handled = false;
58
59 const CommonCompletionElement common_completions[] = {
60 {lldb::eNoCompletion, nullptr},
95 nullptr} // This one has to be last in the list.
96 };
97
98 for (int i = 0; request.ShouldAddCompletions(); i++) {
99 if (common_completions[i].type == lldb::eTerminatorCompletion)
100 break;
101 else if ((common_completions[i].type & completion_mask) ==
102 common_completions[i].type &&
103 common_completions[i].callback != nullptr) {
104 handled = true;
105 common_completions[i].callback(interpreter, request, searcher);
106 }
107 }
108 return handled;
109}
110
111namespace {
112// The Completer class is a convenient base class for building searchers that
113// go along with the SearchFilter passed to the standard Completer functions.
114class Completer : public Searcher {
115public:
116 Completer(CommandInterpreter &interpreter, CompletionRequest &request)
117 : m_interpreter(interpreter), m_request(request) {}
118
119 ~Completer() override = default;
120
121 CallbackReturn SearchCallback(SearchFilter &filter, SymbolContext &context,
122 Address *addr) override = 0;
123
124 lldb::SearchDepth GetDepth() override = 0;
125
126 virtual void DoCompletion(SearchFilter *filter) = 0;
127
128protected:
129 CommandInterpreter &m_interpreter;
130 CompletionRequest &m_request;
131
132private:
133 Completer(const Completer &) = delete;
134 const Completer &operator=(const Completer &) = delete;
135};
136} // namespace
137
138// SourceFileCompleter implements the source file completer
139namespace {
140class SourceFileCompleter : public Completer {
141public:
142 SourceFileCompleter(CommandInterpreter &interpreter,
143 CompletionRequest &request)
144 : Completer(interpreter, request),
145 m_partial_spec(m_request.GetCursorArgumentPrefix()) {}
146
147 lldb::SearchDepth GetDepth() override { return lldb::eSearchDepthCompUnit; }
148
149 Searcher::CallbackReturn SearchCallback(SearchFilter &filter,
150 SymbolContext &context,
151 Address *addr) override {
152 llvm::StringRef spec_file_name = m_partial_spec.GetFilename();
153 llvm::StringRef spec_dir_name = m_partial_spec.GetDirectory();
154 if (context.comp_unit != nullptr) {
155 llvm::StringRef cur_file_name =
157 llvm::StringRef cur_dir_name =
159
160 bool match = false;
161 if (!spec_file_name.empty() && cur_file_name.starts_with(spec_file_name))
162 match = true;
163
164 if (match && !spec_dir_name.empty() &&
165 !cur_dir_name.starts_with(spec_dir_name))
166 match = false;
167
168 if (match) {
169 m_matching_files.AppendIfUnique(context.comp_unit->GetPrimaryFile());
170 }
171 }
172 return m_matching_files.GetSize() >=
173 m_request.GetMaxNumberOfCompletionsToAdd()
176 }
177
178 void DoCompletion(SearchFilter *filter) override {
179 filter->Search(*this);
180 // Now convert the filelist to completions:
181 for (size_t i = 0; i < m_matching_files.GetSize(); i++) {
182 m_request.AddCompletion(
183 m_matching_files.GetFileSpecAtIndex(i).GetFilename());
184 }
185 }
186
187private:
188 FileSpec m_partial_spec;
189 FileSpecList m_matching_files;
190
191 SourceFileCompleter(const SourceFileCompleter &) = delete;
192 const SourceFileCompleter &operator=(const SourceFileCompleter &) = delete;
193};
194} // namespace
195
196static bool regex_chars(const char comp) {
197 return llvm::StringRef("[](){}+.*|^$\\?").contains(comp);
198}
199
200namespace {
201class SymbolCompleter : public Completer {
202
203public:
204 SymbolCompleter(CommandInterpreter &interpreter, CompletionRequest &request)
205 : Completer(interpreter, request) {
206 std::string regex_str;
207 if (!m_request.GetCursorArgumentPrefix().empty()) {
208 regex_str.append("^");
209 regex_str.append(std::string(m_request.GetCursorArgumentPrefix()));
210 } else {
211 // Match anything since the completion string is empty
212 regex_str.append(".");
213 }
214 std::string::iterator pos =
215 find_if(regex_str.begin() + 1, regex_str.end(), regex_chars);
216 while (pos < regex_str.end()) {
217 pos = regex_str.insert(pos, '\\');
218 pos = find_if(pos + 2, regex_str.end(), regex_chars);
219 }
220 m_regex = RegularExpression(regex_str);
221 }
222
223 lldb::SearchDepth GetDepth() override { return lldb::eSearchDepthModule; }
224
225 Searcher::CallbackReturn SearchCallback(SearchFilter &filter,
226 SymbolContext &context,
227 Address *addr) override {
228 if (context.module_sp) {
229 SymbolContextList sc_list;
230 ModuleFunctionSearchOptions function_options;
231 function_options.include_symbols = true;
232 function_options.include_inlines = true;
233 context.module_sp->FindFunctions(m_regex, function_options, sc_list);
234
235 // Now add the functions & symbols to the list - only add if unique:
236 for (const SymbolContext &sc : sc_list) {
237 if (m_match_set.size() >= m_request.GetMaxNumberOfCompletionsToAdd())
238 break;
239
240 ConstString func_name = sc.GetFunctionName(Mangled::ePreferDemangled);
241 // Ensure that the function name matches the regex. This is more than
242 // a sanity check. It is possible that the demangled function name
243 // does not start with the prefix, for example when it's in an
244 // anonymous namespace.
245 if (!func_name.IsEmpty() && m_regex.Execute(func_name.GetStringRef()))
246 m_match_set.insert(func_name);
247 }
248 }
249 return m_match_set.size() >= m_request.GetMaxNumberOfCompletionsToAdd()
252 }
253
254 void DoCompletion(SearchFilter *filter) override {
255 filter->Search(*this);
256 collection::iterator pos = m_match_set.begin(), end = m_match_set.end();
257 for (pos = m_match_set.begin(); pos != end; pos++)
258 m_request.AddCompletion((*pos).GetCString());
259 }
260
261private:
262 RegularExpression m_regex;
263 typedef std::set<ConstString> collection;
264 collection m_match_set;
265
266 SymbolCompleter(const SymbolCompleter &) = delete;
267 const SymbolCompleter &operator=(const SymbolCompleter &) = delete;
268};
269} // namespace
270
271namespace {
272class ModuleCompleter : public Completer {
273public:
274 ModuleCompleter(CommandInterpreter &interpreter, CompletionRequest &request)
275 : Completer(interpreter, request) {
276 llvm::StringRef request_str = m_request.GetCursorArgumentPrefix();
277 // We can match the full path, or the file name only. The full match will be
278 // attempted always, the file name match only if the request does not
279 // contain a path separator.
280
281 // Preserve both the path as spelled by the user (used for completion) and
282 // the canonical version (used for matching).
283 m_spelled_path = request_str;
284 m_canonical_path = FileSpec(m_spelled_path).GetPath();
285 if (!m_spelled_path.empty() &&
286 llvm::sys::path::is_separator(m_spelled_path.back()) &&
287 !llvm::StringRef(m_canonical_path).ends_with(m_spelled_path.back())) {
288 m_canonical_path += m_spelled_path.back();
289 }
290
291 if (llvm::find_if(request_str, [](char c) {
292 return llvm::sys::path::is_separator(c);
293 }) == request_str.end())
294 m_file_name = request_str;
295 }
296
297 lldb::SearchDepth GetDepth() override { return lldb::eSearchDepthModule; }
298
299 Searcher::CallbackReturn SearchCallback(SearchFilter &filter,
300 SymbolContext &context,
301 Address *addr) override {
302 if (context.module_sp) {
303 // Attempt a full path match.
304 std::string cur_path = context.module_sp->GetFileSpec().GetPath();
305 llvm::StringRef cur_path_view = cur_path;
306 if (cur_path_view.consume_front(m_canonical_path))
307 m_request.AddCompletion((m_spelled_path + cur_path_view).str());
308
309 // And a file name match.
310 if (m_file_name) {
311 llvm::StringRef cur_file_name =
312 context.module_sp->GetFileSpec().GetFilename();
313 if (cur_file_name.starts_with(*m_file_name))
314 m_request.AddCompletion(cur_file_name);
315 }
316 }
317 return m_request.ShouldAddCompletions() ? Searcher::eCallbackReturnContinue
319 }
320
321 void DoCompletion(SearchFilter *filter) override { filter->Search(*this); }
322
323private:
324 std::optional<llvm::StringRef> m_file_name;
325 llvm::StringRef m_spelled_path;
326 std::string m_canonical_path;
327
328 ModuleCompleter(const ModuleCompleter &) = delete;
329 const ModuleCompleter &operator=(const ModuleCompleter &) = delete;
330};
331} // namespace
332
334 CompletionRequest &request,
335 SearchFilter *searcher) {
336 SourceFileCompleter completer(interpreter, request);
337
338 if (searcher == nullptr) {
339 lldb::TargetSP target_sp = interpreter.GetSelectedTarget();
340 SearchFilterForUnconstrainedSearches null_searcher(target_sp);
341 completer.DoCompletion(&null_searcher);
342 } else {
343 completer.DoCompletion(searcher);
344 }
345}
346
347static void DiskFilesOrDirectories(const llvm::Twine &partial_name,
348 bool only_directories,
349 CompletionRequest &request,
350 TildeExpressionResolver &Resolver) {
351 llvm::SmallString<256> CompletionBuffer;
352 llvm::SmallString<256> Storage;
353 partial_name.toVector(CompletionBuffer);
354
355 if (CompletionBuffer.size() >= PATH_MAX)
356 return;
357
358 namespace path = llvm::sys::path;
359
360 llvm::StringRef SearchDir;
361 llvm::StringRef PartialItem;
362
363 if (CompletionBuffer.starts_with("~")) {
364 llvm::StringRef Buffer = CompletionBuffer;
365 size_t FirstSep =
366 Buffer.find_if([](char c) { return path::is_separator(c); });
367
368 llvm::StringRef Username = Buffer.take_front(FirstSep);
369 llvm::StringRef Remainder;
370 if (FirstSep != llvm::StringRef::npos)
371 Remainder = Buffer.drop_front(FirstSep + 1);
372
373 llvm::SmallString<256> Resolved;
374 if (!Resolver.ResolveExact(Username, Resolved)) {
375 // We couldn't resolve it as a full username. If there were no slashes
376 // then this might be a partial username. We try to resolve it as such
377 // but after that, we're done regardless of any matches.
378 if (FirstSep == llvm::StringRef::npos) {
379 llvm::StringSet<> MatchSet;
380 Resolver.ResolvePartial(Username, MatchSet);
381 for (const auto &S : MatchSet) {
382 Resolved = S.getKey();
383 path::append(Resolved, path::get_separator());
384 request.AddCompletion(Resolved, "", CompletionMode::Partial);
385 }
386 }
387 return;
388 }
389
390 // If there was no trailing slash, then we're done as soon as we resolve
391 // the expression to the correct directory. Otherwise we need to continue
392 // looking for matches within that directory.
393 if (FirstSep == llvm::StringRef::npos) {
394 // Make sure it ends with a separator.
395 path::append(CompletionBuffer, path::get_separator());
396 request.AddCompletion(CompletionBuffer, "", CompletionMode::Partial);
397 return;
398 }
399
400 // We want to keep the form the user typed, so we special case this to
401 // search in the fully resolved directory, but CompletionBuffer keeps the
402 // unmodified form that the user typed.
403 Storage = Resolved;
404 llvm::StringRef RemainderDir = path::parent_path(Remainder);
405 if (!RemainderDir.empty()) {
406 // Append the remaining path to the resolved directory.
407 Storage.append(path::get_separator());
408 Storage.append(RemainderDir);
409 }
410 SearchDir = Storage;
411 } else if (CompletionBuffer == path::root_directory(CompletionBuffer)) {
412 SearchDir = CompletionBuffer;
413 } else {
414 SearchDir = path::parent_path(CompletionBuffer);
415 }
416
417 size_t FullPrefixLen = CompletionBuffer.size();
418
419 PartialItem = path::filename(CompletionBuffer);
420
421 // path::filename() will return "." when the passed path ends with a
422 // directory separator or the separator when passed the disk root directory.
423 // We have to filter those out, but only when the "." doesn't come from the
424 // completion request itself.
425 if ((PartialItem == "." || PartialItem == path::get_separator()) &&
426 path::is_separator(CompletionBuffer.back()))
427 PartialItem = llvm::StringRef();
428
429 if (SearchDir.empty()) {
430 llvm::sys::fs::current_path(Storage);
431 SearchDir = Storage;
432 }
433 assert(!PartialItem.contains(path::get_separator()));
434
435 // SearchDir now contains the directory to search in, and Prefix contains the
436 // text we want to match against items in that directory.
437
439 std::error_code EC;
440 llvm::vfs::directory_iterator Iter = fs.DirBegin(SearchDir, EC);
441 llvm::vfs::directory_iterator End;
442 for (; Iter != End && !EC && request.ShouldAddCompletions();
443 Iter.increment(EC)) {
444 auto &Entry = *Iter;
445 llvm::ErrorOr<llvm::vfs::Status> Status = fs.GetStatus(Entry.path());
446
447 if (!Status)
448 continue;
449
450 auto Name = path::filename(Entry.path());
451
452 // Omit ".", ".."
453 if (Name == "." || Name == ".." || !Name.starts_with(PartialItem))
454 continue;
455
456 bool is_dir = Status->isDirectory();
457
458 // If it's a symlink, then we treat it as a directory as long as the target
459 // is a directory.
460 if (Status->isSymlink()) {
461 FileSpec symlink_filespec(Entry.path());
462 FileSpec resolved_filespec;
463 auto error = fs.ResolveSymbolicLink(symlink_filespec, resolved_filespec);
464 if (error.Success())
465 is_dir = fs.IsDirectory(symlink_filespec);
466 }
467
468 if (only_directories && !is_dir)
469 continue;
470
471 // Shrink it back down so that it just has the original prefix the user
472 // typed and remove the part of the name which is common to the located
473 // item and what the user typed.
474 CompletionBuffer.resize(FullPrefixLen);
475 Name = Name.drop_front(PartialItem.size());
476 CompletionBuffer.append(Name);
477
478 if (is_dir) {
479 path::append(CompletionBuffer, path::get_separator());
480 }
481
482 CompletionMode mode =
484 request.AddCompletion(CompletionBuffer, "", mode);
485 }
486}
487
488static void DiskFilesOrDirectories(const llvm::Twine &partial_name,
489 bool only_directories, StringList &matches,
490 TildeExpressionResolver &Resolver) {
491 CompletionResult result;
492 std::string partial_name_str = partial_name.str();
493 CompletionRequest request(partial_name_str, partial_name_str.size(), result);
494 DiskFilesOrDirectories(partial_name, only_directories, request, Resolver);
495 result.GetMatches(matches);
496}
497
499 bool only_directories) {
501 DiskFilesOrDirectories(request.GetCursorArgumentPrefix(), only_directories,
502 request, resolver);
503}
504
506 CompletionRequest &request,
507 SearchFilter *searcher) {
508 DiskFilesOrDirectories(request, /*only_dirs*/ false);
509}
510
511void CommandCompletions::DiskFiles(const llvm::Twine &partial_file_name,
512 StringList &matches,
513 TildeExpressionResolver &Resolver) {
514 DiskFilesOrDirectories(partial_file_name, false, matches, Resolver);
515}
516
518 CompletionRequest &request,
519 SearchFilter *searcher) {
520 DiskFilesOrDirectories(request, /*only_dirs*/ true);
521}
522
523void CommandCompletions::DiskDirectories(const llvm::Twine &partial_file_name,
524 StringList &matches,
525 TildeExpressionResolver &Resolver) {
526 DiskFilesOrDirectories(partial_file_name, true, matches, Resolver);
527}
528
530 CompletionRequest &request,
531 SearchFilter *searcher) {
532 lldb::PlatformSP platform_sp =
534 if (platform_sp)
535 platform_sp->AutoCompleteDiskFileOrDirectory(request, false);
536}
537
539 CompletionRequest &request,
540 SearchFilter *searcher) {
541 lldb::PlatformSP platform_sp =
543 if (platform_sp)
544 platform_sp->AutoCompleteDiskFileOrDirectory(request, true);
545}
546
548 CompletionRequest &request,
549 SearchFilter *searcher) {
550 ModuleCompleter completer(interpreter, request);
551
552 if (searcher == nullptr) {
553 lldb::TargetSP target_sp = interpreter.GetSelectedTarget();
554 SearchFilterForUnconstrainedSearches null_searcher(target_sp);
555 completer.DoCompletion(&null_searcher);
556 } else {
557 completer.DoCompletion(searcher);
558 }
559}
560
562 CompletionRequest &request,
563 SearchFilter *searcher) {
564 const ExecutionContext &exe_ctx = interpreter.GetExecutionContext();
565 if (!exe_ctx.HasTargetScope())
566 return;
567
568 exe_ctx.GetTargetPtr()->GetImages().ForEach(
569 [&request](const lldb::ModuleSP &module) {
570 StreamString strm;
571 module->GetDescription(strm.AsRawOstream(),
572 lldb::eDescriptionLevelInitial);
573 request.TryCompleteCurrentArg(module->GetUUID().GetAsString(),
574 strm.GetString());
576 });
577}
578
580 CompletionRequest &request,
581 SearchFilter *searcher) {
582 SymbolCompleter completer(interpreter, request);
583
584 if (searcher == nullptr) {
585 lldb::TargetSP target_sp = interpreter.GetSelectedTarget();
586 SearchFilterForUnconstrainedSearches null_searcher(target_sp);
587 completer.DoCompletion(&null_searcher);
588 } else {
589 completer.DoCompletion(searcher);
590 }
591}
592
594 CompletionRequest &request,
595 SearchFilter *searcher) {
596 // Cache the full setting name/description list.
597 static StringList g_property_names;
598 static StringList g_property_descriptions;
599 if (g_property_names.GetSize() == 0) {
600 // Generate the full setting name list on demand
601 lldb::OptionValuePropertiesSP properties_sp(
602 interpreter.GetDebugger().GetValueProperties());
603 if (properties_sp) {
604 StreamString strm;
605 properties_sp->DumpValue(nullptr, strm, OptionValue::eDumpOptionName);
606 const std::string &str = std::string(strm.GetString());
607 g_property_names.SplitIntoLines(str.c_str(), str.size());
608
609 // Look up the description for each setting name so it can be displayed
610 // alongside the completion.
611 for (const std::string &name : g_property_names) {
612 std::string description;
613 if (const Property *property =
614 properties_sp->GetPropertyAtPath(nullptr, name))
615 description = property->GetDescription().str();
616 g_property_descriptions.AppendString(description);
617 }
618 }
619 }
620
621 assert(g_property_names.GetSize() == g_property_descriptions.GetSize() &&
622 "Not all properties got descriptions?");
623 for (size_t i = 0; i < g_property_names.GetSize(); ++i)
624 request.TryCompleteCurrentArg(g_property_names[i],
625 g_property_descriptions[i]);
626}
627
634
636 CompletionRequest &request,
637 SearchFilter *searcher) {
638 ArchSpec::AutoComplete(request);
639}
640
642 CompletionRequest &request,
643 SearchFilter *searcher) {
644 Variable::AutoComplete(interpreter.GetExecutionContext(), request);
645}
646
648 CompletionRequest &request,
649 SearchFilter *searcher) {
650 std::string reg_prefix;
651 if (request.GetCursorArgumentPrefix().starts_with("$"))
652 reg_prefix = "$";
653
654 RegisterContext *reg_ctx =
656 if (!reg_ctx)
657 return;
658
659 const size_t reg_num = reg_ctx->GetRegisterCount();
660 for (size_t reg_idx = 0; reg_idx < reg_num; ++reg_idx) {
661 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_idx);
662 request.TryCompleteCurrentArg(reg_prefix + reg_info->name,
663 reg_info->alt_name);
664 }
665}
666
668 CompletionRequest &request,
669 SearchFilter *searcher) {
670 lldb::TargetSP target = interpreter.GetSelectedTarget();
671 if (!target)
672 return;
673
674 const BreakpointList &breakpoints = target->GetBreakpointList();
675
676 std::unique_lock<std::recursive_mutex> lock;
677 target->GetBreakpointList().GetListMutex(lock);
678
679 size_t num_breakpoints = breakpoints.GetSize();
680 if (num_breakpoints == 0)
681 return;
682
683 for (size_t i = 0; i < num_breakpoints; ++i) {
684 lldb::BreakpointSP bp = breakpoints.GetBreakpointAtIndex(i);
685
686 StreamString s;
687 bp->GetDescription(&s, lldb::eDescriptionLevelBrief);
688 llvm::StringRef bp_info = s.GetString();
689
690 const size_t colon_pos = bp_info.find_first_of(':');
691 if (colon_pos != llvm::StringRef::npos)
692 bp_info = bp_info.drop_front(colon_pos + 2);
693
694 request.TryCompleteCurrentArg(std::to_string(bp->GetID()), bp_info);
695 }
696}
697
699 CompletionRequest &request,
700 SearchFilter *searcher) {
701 lldb::TargetSP target = interpreter.GetSelectedTarget();
702 if (!target)
703 return;
704
705 std::vector<std::string> name_list;
706 target->GetBreakpointNames(name_list);
707
708 for (const std::string &name : name_list)
709 request.TryCompleteCurrentArg(name);
710}
711
719 CompletionRequest &request,
720 SearchFilter *searcher) {
721 // Currently the only valid options for disassemble -F are default, and for
722 // Intel architectures, att and intel.
723 static const char *flavors[] = {"default", "att", "intel"};
724 for (const char *flavor : flavors) {
725 request.TryCompleteCurrentArg(flavor);
726 }
727}
728
730 CompletionRequest &request,
731 SearchFilter *searcher) {
732 lldb::PlatformSP platform_sp(interpreter.GetPlatform(true));
733 if (!platform_sp)
734 return;
735 ProcessInstanceInfoList process_infos;
736 ProcessInstanceInfoMatch match_info;
737 platform_sp->FindProcesses(match_info, process_infos);
738 for (const ProcessInstanceInfo &info : process_infos)
739 request.TryCompleteCurrentArg(std::to_string(info.GetProcessID()),
740 info.GetName());
741}
742
744 CompletionRequest &request,
745 SearchFilter *searcher) {
746 lldb::PlatformSP platform_sp(interpreter.GetPlatform(true));
747 if (!platform_sp)
748 return;
749 ProcessInstanceInfoList process_infos;
750 ProcessInstanceInfoMatch match_info;
751 platform_sp->FindProcesses(match_info, process_infos);
752 for (const ProcessInstanceInfo &info : process_infos)
753 request.TryCompleteCurrentArg(info.GetName());
754}
755
757 CompletionRequest &request,
758 SearchFilter *searcher) {
759 for (int bit :
760 Language::GetLanguagesSupportingTypeSystems().bitvector.set_bits()) {
761 request.TryCompleteCurrentArg(
763 }
764}
765
767 CompletionRequest &request,
768 SearchFilter *searcher) {
769 const ExecutionContext &exe_ctx = interpreter.GetExecutionContext();
770 if (!exe_ctx.HasProcessScope())
771 return;
772
773 lldb::ThreadSP thread_sp = exe_ctx.GetThreadSP();
774 Debugger &dbg = interpreter.GetDebugger();
775 const uint32_t frame_num = thread_sp->GetStackFrameCount();
776 for (uint32_t i = 0; i < frame_num; ++i) {
777 lldb::StackFrameSP frame_sp = thread_sp->GetStackFrameAtIndex(i);
778 StreamString strm;
779 // Dumping frames can be slow, allow interruption.
780 if (INTERRUPT_REQUESTED(dbg, "Interrupted in frame completion"))
781 break;
782 frame_sp->Dump(&strm, false, true);
783 request.TryCompleteCurrentArg(std::to_string(i), strm.GetString());
784 }
785}
786
788 CompletionRequest &request,
789 SearchFilter *searcher) {
790 const lldb::TargetSP target_sp =
791 interpreter.GetExecutionContext().GetTargetSP();
792 if (!target_sp)
793 return;
794
795 for (auto &stophook_sp : target_sp->GetStopHooks()) {
796 StreamString strm;
797 // The value 11 is an offset to make the completion description looks
798 // neater.
799 strm.SetIndentLevel(11);
800 stophook_sp->GetDescription(strm, lldb::eDescriptionLevelInitial);
801 request.TryCompleteCurrentArg(std::to_string(stophook_sp->GetID()),
802 strm.GetString());
803 }
804}
805
807 CompletionRequest &request,
808 SearchFilter *searcher) {
809 const ExecutionContext &exe_ctx = interpreter.GetExecutionContext();
810 if (!exe_ctx.HasProcessScope())
811 return;
812
813 ThreadList &threads = exe_ctx.GetProcessPtr()->GetThreadList();
814 lldb::ThreadSP thread_sp;
815 for (uint32_t idx = 0; (thread_sp = threads.GetThreadAtIndex(idx)); ++idx) {
816 StreamString strm;
817 thread_sp->GetStatus(strm, 0, 1, 1, true, /*show_hidden*/ true);
818 request.TryCompleteCurrentArg(std::to_string(thread_sp->GetIndexID()),
819 strm.GetString());
820 }
821}
822
824 CompletionRequest &request,
825 SearchFilter *searcher) {
826 const ExecutionContext &exe_ctx = interpreter.GetExecutionContext();
827 if (!exe_ctx.HasTargetScope())
828 return;
829
830 const WatchpointList &wp_list = exe_ctx.GetTargetPtr()->GetWatchpointList();
831 for (lldb::WatchpointSP wp_sp : wp_list.Watchpoints()) {
832 StreamString strm;
833 wp_sp->Dump(&strm);
834 request.TryCompleteCurrentArg(std::to_string(wp_sp->GetID()),
835 strm.GetString());
836 }
837}
838
840 CompletionRequest &request,
841 SearchFilter *searcher) {
843 [&request](const lldb::TypeCategoryImplSP &category_sp) {
844 request.TryCompleteCurrentArg(category_sp->GetName(),
845 category_sp->GetDescription());
846 return true;
847 });
848}
849
851 CompletionRequest &request,
852 SearchFilter *searcher) {
853 const ExecutionContext &exe_ctx = interpreter.GetExecutionContext();
854 if (!exe_ctx.HasProcessScope())
855 return;
856
857 ThreadList &threads = exe_ctx.GetProcessPtr()->GetThreadList();
858 lldb::ThreadSP thread_sp;
859 for (uint32_t idx = 0; (thread_sp = threads.GetThreadAtIndex(idx)); ++idx) {
860 StreamString strm;
861 thread_sp->GetStatus(strm, 0, 1, 1, true, /*show_hidden*/ true);
862 request.TryCompleteCurrentArg(std::to_string(thread_sp->GetID()),
863 strm.GetString());
864 }
865}
866
873
880
882 CommandInterpreter &interpreter, CompletionRequest &request,
883 OptionElementVector &opt_element_vector) {
884 // The only arguments constitute a command path, however, there might be
885 // options interspersed among the arguments, and we need to skip those. Do that
886 // by copying the args vector, and just dropping all the option bits:
887 Args args = request.GetParsedLine();
888 std::vector<size_t> to_delete;
889 for (auto &elem : opt_element_vector) {
890 to_delete.push_back(elem.opt_pos);
891 if (elem.opt_arg_pos != 0)
892 to_delete.push_back(elem.opt_arg_pos);
893 }
894 sort(to_delete.begin(), to_delete.end(), std::greater<size_t>());
895 for (size_t idx : to_delete)
896 args.DeleteArgumentAtIndex(idx);
897
898 // At this point, we should only have args, so now lookup the command up to
899 // the cursor element.
900
901 // There's nothing here but options. It doesn't seem very useful here to
902 // dump all the commands, so just return.
903 size_t num_args = args.GetArgumentCount();
904 if (num_args == 0)
905 return;
906
907 // There's just one argument, so we should complete its name:
908 StringList matches;
909 if (num_args == 1) {
910 interpreter.GetUserCommandObject(args.GetArgumentAtIndex(0), &matches,
911 nullptr);
912 request.AddCompletions(matches);
913 return;
914 }
915
916 // There was more than one path element, lets find the containing command:
919 interpreter.VerifyUserMultiwordCmdPath(args, true, error);
920
921 // Something was wrong somewhere along the path, but I don't think there's
922 // a good way to go back and fill in the missing elements:
923 if (error.Fail())
924 return;
925
926 // This should never happen. We already handled the case of one argument
927 // above, and we can only get Success & nullptr back if there's a one-word
928 // leaf.
929 assert(mwc != nullptr);
930
931 mwc->GetSubcommandObject(args.GetArgumentAtIndex(num_args - 1), &matches);
932 if (matches.GetSize() == 0)
933 return;
934
935 request.AddCompletions(matches);
936}
static void DiskFilesOrDirectories(const llvm::Twine &partial_name, bool only_directories, CompletionRequest &request, TildeExpressionResolver &Resolver)
static bool regex_chars(const char comp)
void(* CompletionCallback)(CommandInterpreter &interpreter, CompletionRequest &request, lldb_private::SearchFilter *searcher)
static llvm::raw_ostream & error(Stream &strm)
#define INTERRUPT_REQUESTED(debugger,...)
This handy define will keep you from having to generate a report for the interruption by hand.
Definition Debugger.h:502
FormatEntity::Entry Entry
A section + offset based address class.
Definition Address.h:62
static void AutoComplete(CompletionRequest &request)
Definition ArchSpec.cpp:391
A command line argument class.
Definition Args.h:33
void DeleteArgumentAtIndex(size_t idx)
Deletes the argument value at index if idx is a valid argument index.
Definition Args.cpp:359
size_t GetArgumentCount() const
Gets the number of arguments left in this command object.
Definition Args.h:120
const char * GetArgumentAtIndex(size_t idx) const
Gets the NULL terminated C string argument pointer for the argument at index idx.
Definition Args.cpp:273
General Outline: Allows adding and removing breakpoints and find by ID and index.
size_t GetSize() const
Returns the number of elements in this breakpoint list.
lldb::BreakpointSP GetBreakpointAtIndex(size_t i) const
Returns a shared pointer to the breakpoint with index i.
static void DisassemblyFlavors(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher)
static bool InvokeCommonCompletionCallbacks(CommandInterpreter &interpreter, uint32_t completion_mask, lldb_private::CompletionRequest &request, SearchFilter *searcher)
static void ArchitectureNames(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher)
static void DiskDirectories(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher)
static void RemoteDiskDirectories(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher)
static void ManagedPlugins(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher)
static void SourceFiles(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher)
static void Registers(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher)
static void TypeLanguages(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher)
static void DiskFiles(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher)
static void ProcessPluginNames(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher)
static void PlatformPluginNames(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher)
static void Breakpoints(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher)
static void ThreadIDs(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher)
static void ProcessIDs(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher)
static void Symbols(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher)
static void StopHookIDs(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher)
static void ModuleUUIDs(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher)
static void ThreadIndexes(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher)
static void SettingsNames(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher)
static void CompleteModifiableCmdPathArgs(CommandInterpreter &interpreter, CompletionRequest &request, OptionElementVector &opt_element_vector)
This completer works for commands whose only arguments are a command path.
static void FrameIndexes(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher)
static void TypeCategoryNames(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher)
static void WatchPointIDs(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher)
static void Modules(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher)
static void RemoteDiskFiles(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher)
static void ProcessNames(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher)
static void VariablePath(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher)
static void BreakpointNames(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher)
static void ScriptedExtensions(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher)
lldb::TargetSP GetSelectedTarget()
Get the target selected by the user at the command line.
CommandObject * GetUserCommandObject(llvm::StringRef cmd, StringList *matches=nullptr, StringList *descriptions=nullptr) const
CommandObjectMultiword * VerifyUserMultiwordCmdPath(Args &path, bool leaf_is_command, Status &result)
Look up the command pointed to by path encoded in the arguments of the incoming command object.
lldb::PlatformSP GetPlatform(bool prefer_target_platform)
ExecutionContext GetExecutionContext(bool adopt_dummy_target=true) const
Returns the execution context the interpreter should run a command in.
CommandObject * GetSubcommandObject(llvm::StringRef sub_cmd, StringList *matches=nullptr) override
const FileSpec & GetPrimaryFile() const
Return the primary source spec associated with this compile unit.
"lldb/Utility/ArgCompletionRequest.h"
void AddCompletion(llvm::StringRef completion, llvm::StringRef description="", CompletionMode mode=CompletionMode::Normal)
Adds a possible completion string.
void AddCompletions(const StringList &completions)
Adds multiple possible completion strings.
llvm::StringRef GetCursorArgumentPrefix() const
bool ShouldAddCompletions() const
Returns true if the maximum number of completions has not been reached yet, hence we should keep addi...
void TryCompleteCurrentArg(llvm::StringRef completion, llvm::StringRef description="")
Adds a possible completion string if the completion would complete the current argument.
void GetMatches(StringList &matches) const
Adds all collected completion matches to the given list.
bool IsEmpty() const
Test for empty string.
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
static void ForEach(TypeCategoryMap::ForEachCallback callback)
A class to manage flag bits.
Definition Debugger.h:100
PlatformList & GetPlatformList()
Definition Debugger.h:222
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
bool HasProcessScope() const
Returns true the ExecutionContext object contains a valid target and process.
const lldb::TargetSP & GetTargetSP() const
Get accessor to get the target shared pointer.
Target * GetTargetPtr() const
Returns a pointer to the target object.
const lldb::ThreadSP & GetThreadSP() const
Get accessor to get the thread shared pointer.
bool HasTargetScope() const
Returns true the ExecutionContext object contains a valid target.
Process * GetProcessPtr() const
Returns a pointer to the process object.
RegisterContext * GetRegisterContext() const
A file utility class.
Definition FileSpec.h:57
llvm::StringRef GetFilename() const
Filename string const get accessor.
Definition FileSpec.h:249
llvm::StringRef GetDirectory() const
Directory string const get accessor.
Definition FileSpec.h:234
Status ResolveSymbolicLink(const FileSpec &src, FileSpec &dst)
llvm::vfs::directory_iterator DirBegin(const FileSpec &file_spec, std::error_code &ec)
Get a directory iterator.
llvm::ErrorOr< llvm::vfs::Status > GetStatus(const FileSpec &file_spec) const
Returns the Status object for the given file.
bool IsDirectory(const FileSpec &file_spec) const
Returns whether the given path is a directory.
static FileSystem & Instance()
static LanguageSet GetLanguagesSupportingTypeSystems()
Definition Language.cpp:467
static const char * GetNameForLanguageType(lldb::LanguageType language)
Returns the internal LLDB name for the specified language.
Definition Language.cpp:305
void ForEach(std::function< IterationAction(const lldb::ModuleSP &module_sp)> const &callback) const
Applies 'callback' to each module in this ModuleList.
lldb::PlatformSP GetSelectedPlatform()
Select the active platform.
Definition Platform.h:1185
static void AutoCompleteScriptedExtension(llvm::StringRef partial_name, CompletionRequest &request, lldb::ScriptLanguage language=lldb::eScriptLanguageUnknown)
static void AutoCompletePlatformName(llvm::StringRef partial_name, CompletionRequest &request)
static void AutoCompleteProcessName(llvm::StringRef partial_name, CompletionRequest &request)
static void AutoCompletePluginName(llvm::StringRef partial_name, CompletionRequest &request)
ThreadList & GetThreadList()
Definition Process.h:2394
lldb::OptionValuePropertiesSP GetValueProperties() const
virtual const RegisterInfo * GetRegisterInfoAtIndex(size_t reg)=0
virtual size_t GetRegisterCount()=0
"lldb/Core/SearchFilter.h" This is a SearchFilter that searches through all modules.
General Outline: Provides the callback and search depth for the SearchFilter search.
virtual void Search(Searcher &searcher)
Call this method to do the search using the Searcher.
General Outline: Provides the callback and search depth for the SearchFilter search.
An error handling class.
Definition Status.h:118
llvm::StringRef GetString() const
void SetIndentLevel(unsigned level)
Set the current indentation level.
Definition Stream.cpp:196
size_t SplitIntoLines(const std::string &lines)
void AppendString(const std::string &s)
Defines a symbol context baton that can be handed other debug core functions.
lldb::ModuleSP module_sp
The Module for a given query.
CompileUnit * comp_unit
The CompileUnit for a given query.
const ModuleList & GetImages() const
Get accessor for the images for this process.
Definition Target.h:1247
WatchpointList & GetWatchpointList()
Definition Target.h:959
lldb::ThreadSP GetThreadAtIndex(uint32_t idx, bool can_update=true)
virtual bool ResolveExact(llvm::StringRef Expr, llvm::SmallVectorImpl< char > &Output)=0
Resolve a Tilde Expression contained according to bash rules.
virtual bool ResolvePartial(llvm::StringRef Expr, llvm::StringSet<> &Output)=0
Auto-complete a tilde expression with all matching values.
static void AutoComplete(const ExecutionContext &exe_ctx, CompletionRequest &request)
Definition Variable.cpp:770
This class is used by Watchpoint to manage a list of watchpoints,.
WatchpointIterable Watchpoints() const
A class that represents a running process on the host machine.
static uint32_t bit(const uint32_t val, const uint32_t msbit)
Definition ARMUtils.h:270
std::vector< OptionArgElement > OptionElementVector
Definition Options.h:43
@ Partial
The current token has been partially completed.
@ Normal
The current token has been completed.
std::vector< ProcessInstanceInfo > ProcessInstanceInfoList
Definition Host.h:32
@ eRemoteDiskDirectoryCompletion
@ eFrameIndexCompletion
@ eModuleUUIDCompletion
@ eDisassemblyFlavorCompletion
@ eVariablePathCompletion
@ eDiskDirectoryCompletion
@ eTypeCategoryNameCompletion
@ ePlatformPluginCompletion
@ eSettingsNameCompletion
@ eSourceFileCompletion
@ eTypeLanguageCompletion
@ eStopHookIDCompletion
@ eWatchpointIDCompletion
@ eBreakpointNameCompletion
@ eProcessPluginCompletion
@ eRemoteDiskFileCompletion
@ eBreakpointCompletion
@ eThreadIndexCompletion
@ eArchitectureCompletion
@ eScriptedExtensionCompletion
@ eProcessNameCompletion
@ eManagedPluginCompletion
@ eTerminatorCompletion
std::shared_ptr< lldb_private::OptionValueProperties > OptionValuePropertiesSP
std::shared_ptr< lldb_private::StackFrame > StackFrameSP
@ eDescriptionLevelBrief
@ eDescriptionLevelInitial
std::shared_ptr< lldb_private::Thread > ThreadSP
std::shared_ptr< lldb_private::Platform > PlatformSP
LanguageType
Programming language type.
std::shared_ptr< lldb_private::Breakpoint > BreakpointSP
std::shared_ptr< lldb_private::Watchpoint > WatchpointSP
@ eSearchDepthCompUnit
std::shared_ptr< lldb_private::TypeCategoryImpl > TypeCategoryImplSP
std::shared_ptr< lldb_private::Target > TargetSP
std::shared_ptr< lldb_private::Module > ModuleSP
bool include_inlines
Include inlined functions.
Definition Module.h:71
bool include_symbols
Include the symbol table.
Definition Module.h:69
Every register is described in detail including its name, alternate name (optional),...
const char * alt_name
Alternate name of this register, can be NULL.
const char * name
Name of this register, can't be NULL.
#define PATH_MAX