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},
93 nullptr} // This one has to be last in the list.
94 };
95
96 for (int i = 0; request.ShouldAddCompletions(); i++) {
97 if (common_completions[i].type == lldb::eTerminatorCompletion)
98 break;
99 else if ((common_completions[i].type & completion_mask) ==
100 common_completions[i].type &&
101 common_completions[i].callback != nullptr) {
102 handled = true;
103 common_completions[i].callback(interpreter, request, searcher);
104 }
105 }
106 return handled;
107}
108
109namespace {
110// The Completer class is a convenient base class for building searchers that
111// go along with the SearchFilter passed to the standard Completer functions.
112class Completer : public Searcher {
113public:
114 Completer(CommandInterpreter &interpreter, CompletionRequest &request)
115 : m_interpreter(interpreter), m_request(request) {}
116
117 ~Completer() override = default;
118
119 CallbackReturn SearchCallback(SearchFilter &filter, SymbolContext &context,
120 Address *addr) override = 0;
121
122 lldb::SearchDepth GetDepth() override = 0;
123
124 virtual void DoCompletion(SearchFilter *filter) = 0;
125
126protected:
127 CommandInterpreter &m_interpreter;
128 CompletionRequest &m_request;
129
130private:
131 Completer(const Completer &) = delete;
132 const Completer &operator=(const Completer &) = delete;
133};
134} // namespace
135
136// SourceFileCompleter implements the source file completer
137namespace {
138class SourceFileCompleter : public Completer {
139public:
140 SourceFileCompleter(CommandInterpreter &interpreter,
141 CompletionRequest &request)
142 : Completer(interpreter, request),
143 m_partial_spec(m_request.GetCursorArgumentPrefix()) {}
144
145 lldb::SearchDepth GetDepth() override { return lldb::eSearchDepthCompUnit; }
146
147 Searcher::CallbackReturn SearchCallback(SearchFilter &filter,
148 SymbolContext &context,
149 Address *addr) override {
150 llvm::StringRef spec_file_name = m_partial_spec.GetFilename();
151 llvm::StringRef spec_dir_name = m_partial_spec.GetDirectory();
152 if (context.comp_unit != nullptr) {
153 llvm::StringRef cur_file_name =
155 llvm::StringRef cur_dir_name =
157
158 bool match = false;
159 if (!spec_file_name.empty() && cur_file_name.starts_with(spec_file_name))
160 match = true;
161
162 if (match && !spec_dir_name.empty() &&
163 !cur_dir_name.starts_with(spec_dir_name))
164 match = false;
165
166 if (match) {
167 m_matching_files.AppendIfUnique(context.comp_unit->GetPrimaryFile());
168 }
169 }
170 return m_matching_files.GetSize() >=
171 m_request.GetMaxNumberOfCompletionsToAdd()
174 }
175
176 void DoCompletion(SearchFilter *filter) override {
177 filter->Search(*this);
178 // Now convert the filelist to completions:
179 for (size_t i = 0; i < m_matching_files.GetSize(); i++) {
180 m_request.AddCompletion(
181 m_matching_files.GetFileSpecAtIndex(i).GetFilename());
182 }
183 }
184
185private:
186 FileSpec m_partial_spec;
187 FileSpecList m_matching_files;
188
189 SourceFileCompleter(const SourceFileCompleter &) = delete;
190 const SourceFileCompleter &operator=(const SourceFileCompleter &) = delete;
191};
192} // namespace
193
194static bool regex_chars(const char comp) {
195 return llvm::StringRef("[](){}+.*|^$\\?").contains(comp);
196}
197
198namespace {
199class SymbolCompleter : public Completer {
200
201public:
202 SymbolCompleter(CommandInterpreter &interpreter, CompletionRequest &request)
203 : Completer(interpreter, request) {
204 std::string regex_str;
205 if (!m_request.GetCursorArgumentPrefix().empty()) {
206 regex_str.append("^");
207 regex_str.append(std::string(m_request.GetCursorArgumentPrefix()));
208 } else {
209 // Match anything since the completion string is empty
210 regex_str.append(".");
211 }
212 std::string::iterator pos =
213 find_if(regex_str.begin() + 1, regex_str.end(), regex_chars);
214 while (pos < regex_str.end()) {
215 pos = regex_str.insert(pos, '\\');
216 pos = find_if(pos + 2, regex_str.end(), regex_chars);
217 }
218 m_regex = RegularExpression(regex_str);
219 }
220
221 lldb::SearchDepth GetDepth() override { return lldb::eSearchDepthModule; }
222
223 Searcher::CallbackReturn SearchCallback(SearchFilter &filter,
224 SymbolContext &context,
225 Address *addr) override {
226 if (context.module_sp) {
227 SymbolContextList sc_list;
228 ModuleFunctionSearchOptions function_options;
229 function_options.include_symbols = true;
230 function_options.include_inlines = true;
231 context.module_sp->FindFunctions(m_regex, function_options, sc_list);
232
233 // Now add the functions & symbols to the list - only add if unique:
234 for (const SymbolContext &sc : sc_list) {
235 if (m_match_set.size() >= m_request.GetMaxNumberOfCompletionsToAdd())
236 break;
237
238 ConstString func_name = sc.GetFunctionName(Mangled::ePreferDemangled);
239 // Ensure that the function name matches the regex. This is more than
240 // a sanity check. It is possible that the demangled function name
241 // does not start with the prefix, for example when it's in an
242 // anonymous namespace.
243 if (!func_name.IsEmpty() && m_regex.Execute(func_name.GetStringRef()))
244 m_match_set.insert(func_name);
245 }
246 }
247 return m_match_set.size() >= m_request.GetMaxNumberOfCompletionsToAdd()
250 }
251
252 void DoCompletion(SearchFilter *filter) override {
253 filter->Search(*this);
254 collection::iterator pos = m_match_set.begin(), end = m_match_set.end();
255 for (pos = m_match_set.begin(); pos != end; pos++)
256 m_request.AddCompletion((*pos).GetCString());
257 }
258
259private:
260 RegularExpression m_regex;
261 typedef std::set<ConstString> collection;
262 collection m_match_set;
263
264 SymbolCompleter(const SymbolCompleter &) = delete;
265 const SymbolCompleter &operator=(const SymbolCompleter &) = delete;
266};
267} // namespace
268
269namespace {
270class ModuleCompleter : public Completer {
271public:
272 ModuleCompleter(CommandInterpreter &interpreter, CompletionRequest &request)
273 : Completer(interpreter, request) {
274 llvm::StringRef request_str = m_request.GetCursorArgumentPrefix();
275 // We can match the full path, or the file name only. The full match will be
276 // attempted always, the file name match only if the request does not
277 // contain a path separator.
278
279 // Preserve both the path as spelled by the user (used for completion) and
280 // the canonical version (used for matching).
281 m_spelled_path = request_str;
282 m_canonical_path = FileSpec(m_spelled_path).GetPath();
283 if (!m_spelled_path.empty() &&
284 llvm::sys::path::is_separator(m_spelled_path.back()) &&
285 !llvm::StringRef(m_canonical_path).ends_with(m_spelled_path.back())) {
286 m_canonical_path += m_spelled_path.back();
287 }
288
289 if (llvm::find_if(request_str, [](char c) {
290 return llvm::sys::path::is_separator(c);
291 }) == request_str.end())
292 m_file_name = request_str;
293 }
294
295 lldb::SearchDepth GetDepth() override { return lldb::eSearchDepthModule; }
296
297 Searcher::CallbackReturn SearchCallback(SearchFilter &filter,
298 SymbolContext &context,
299 Address *addr) override {
300 if (context.module_sp) {
301 // Attempt a full path match.
302 std::string cur_path = context.module_sp->GetFileSpec().GetPath();
303 llvm::StringRef cur_path_view = cur_path;
304 if (cur_path_view.consume_front(m_canonical_path))
305 m_request.AddCompletion((m_spelled_path + cur_path_view).str());
306
307 // And a file name match.
308 if (m_file_name) {
309 llvm::StringRef cur_file_name =
310 context.module_sp->GetFileSpec().GetFilename();
311 if (cur_file_name.starts_with(*m_file_name))
312 m_request.AddCompletion(cur_file_name);
313 }
314 }
315 return m_request.ShouldAddCompletions() ? Searcher::eCallbackReturnContinue
317 }
318
319 void DoCompletion(SearchFilter *filter) override { filter->Search(*this); }
320
321private:
322 std::optional<llvm::StringRef> m_file_name;
323 llvm::StringRef m_spelled_path;
324 std::string m_canonical_path;
325
326 ModuleCompleter(const ModuleCompleter &) = delete;
327 const ModuleCompleter &operator=(const ModuleCompleter &) = delete;
328};
329} // namespace
330
332 CompletionRequest &request,
333 SearchFilter *searcher) {
334 SourceFileCompleter completer(interpreter, request);
335
336 if (searcher == nullptr) {
337 lldb::TargetSP target_sp = interpreter.GetSelectedTarget();
338 SearchFilterForUnconstrainedSearches null_searcher(target_sp);
339 completer.DoCompletion(&null_searcher);
340 } else {
341 completer.DoCompletion(searcher);
342 }
343}
344
345static void DiskFilesOrDirectories(const llvm::Twine &partial_name,
346 bool only_directories,
347 CompletionRequest &request,
348 TildeExpressionResolver &Resolver) {
349 llvm::SmallString<256> CompletionBuffer;
350 llvm::SmallString<256> Storage;
351 partial_name.toVector(CompletionBuffer);
352
353 if (CompletionBuffer.size() >= PATH_MAX)
354 return;
355
356 namespace path = llvm::sys::path;
357
358 llvm::StringRef SearchDir;
359 llvm::StringRef PartialItem;
360
361 if (CompletionBuffer.starts_with("~")) {
362 llvm::StringRef Buffer = CompletionBuffer;
363 size_t FirstSep =
364 Buffer.find_if([](char c) { return path::is_separator(c); });
365
366 llvm::StringRef Username = Buffer.take_front(FirstSep);
367 llvm::StringRef Remainder;
368 if (FirstSep != llvm::StringRef::npos)
369 Remainder = Buffer.drop_front(FirstSep + 1);
370
371 llvm::SmallString<256> Resolved;
372 if (!Resolver.ResolveExact(Username, Resolved)) {
373 // We couldn't resolve it as a full username. If there were no slashes
374 // then this might be a partial username. We try to resolve it as such
375 // but after that, we're done regardless of any matches.
376 if (FirstSep == llvm::StringRef::npos) {
377 llvm::StringSet<> MatchSet;
378 Resolver.ResolvePartial(Username, MatchSet);
379 for (const auto &S : MatchSet) {
380 Resolved = S.getKey();
381 path::append(Resolved, path::get_separator());
382 request.AddCompletion(Resolved, "", CompletionMode::Partial);
383 }
384 }
385 return;
386 }
387
388 // If there was no trailing slash, then we're done as soon as we resolve
389 // the expression to the correct directory. Otherwise we need to continue
390 // looking for matches within that directory.
391 if (FirstSep == llvm::StringRef::npos) {
392 // Make sure it ends with a separator.
393 path::append(CompletionBuffer, path::get_separator());
394 request.AddCompletion(CompletionBuffer, "", CompletionMode::Partial);
395 return;
396 }
397
398 // We want to keep the form the user typed, so we special case this to
399 // search in the fully resolved directory, but CompletionBuffer keeps the
400 // unmodified form that the user typed.
401 Storage = Resolved;
402 llvm::StringRef RemainderDir = path::parent_path(Remainder);
403 if (!RemainderDir.empty()) {
404 // Append the remaining path to the resolved directory.
405 Storage.append(path::get_separator());
406 Storage.append(RemainderDir);
407 }
408 SearchDir = Storage;
409 } else if (CompletionBuffer == path::root_directory(CompletionBuffer)) {
410 SearchDir = CompletionBuffer;
411 } else {
412 SearchDir = path::parent_path(CompletionBuffer);
413 }
414
415 size_t FullPrefixLen = CompletionBuffer.size();
416
417 PartialItem = path::filename(CompletionBuffer);
418
419 // path::filename() will return "." when the passed path ends with a
420 // directory separator or the separator when passed the disk root directory.
421 // We have to filter those out, but only when the "." doesn't come from the
422 // completion request itself.
423 if ((PartialItem == "." || PartialItem == path::get_separator()) &&
424 path::is_separator(CompletionBuffer.back()))
425 PartialItem = llvm::StringRef();
426
427 if (SearchDir.empty()) {
428 llvm::sys::fs::current_path(Storage);
429 SearchDir = Storage;
430 }
431 assert(!PartialItem.contains(path::get_separator()));
432
433 // SearchDir now contains the directory to search in, and Prefix contains the
434 // text we want to match against items in that directory.
435
437 std::error_code EC;
438 llvm::vfs::directory_iterator Iter = fs.DirBegin(SearchDir, EC);
439 llvm::vfs::directory_iterator End;
440 for (; Iter != End && !EC && request.ShouldAddCompletions();
441 Iter.increment(EC)) {
442 auto &Entry = *Iter;
443 llvm::ErrorOr<llvm::vfs::Status> Status = fs.GetStatus(Entry.path());
444
445 if (!Status)
446 continue;
447
448 auto Name = path::filename(Entry.path());
449
450 // Omit ".", ".."
451 if (Name == "." || Name == ".." || !Name.starts_with(PartialItem))
452 continue;
453
454 bool is_dir = Status->isDirectory();
455
456 // If it's a symlink, then we treat it as a directory as long as the target
457 // is a directory.
458 if (Status->isSymlink()) {
459 FileSpec symlink_filespec(Entry.path());
460 FileSpec resolved_filespec;
461 auto error = fs.ResolveSymbolicLink(symlink_filespec, resolved_filespec);
462 if (error.Success())
463 is_dir = fs.IsDirectory(symlink_filespec);
464 }
465
466 if (only_directories && !is_dir)
467 continue;
468
469 // Shrink it back down so that it just has the original prefix the user
470 // typed and remove the part of the name which is common to the located
471 // item and what the user typed.
472 CompletionBuffer.resize(FullPrefixLen);
473 Name = Name.drop_front(PartialItem.size());
474 CompletionBuffer.append(Name);
475
476 if (is_dir) {
477 path::append(CompletionBuffer, path::get_separator());
478 }
479
480 CompletionMode mode =
482 request.AddCompletion(CompletionBuffer, "", mode);
483 }
484}
485
486static void DiskFilesOrDirectories(const llvm::Twine &partial_name,
487 bool only_directories, StringList &matches,
488 TildeExpressionResolver &Resolver) {
489 CompletionResult result;
490 std::string partial_name_str = partial_name.str();
491 CompletionRequest request(partial_name_str, partial_name_str.size(), result);
492 DiskFilesOrDirectories(partial_name, only_directories, request, Resolver);
493 result.GetMatches(matches);
494}
495
497 bool only_directories) {
499 DiskFilesOrDirectories(request.GetCursorArgumentPrefix(), only_directories,
500 request, resolver);
501}
502
504 CompletionRequest &request,
505 SearchFilter *searcher) {
506 DiskFilesOrDirectories(request, /*only_dirs*/ false);
507}
508
509void CommandCompletions::DiskFiles(const llvm::Twine &partial_file_name,
510 StringList &matches,
511 TildeExpressionResolver &Resolver) {
512 DiskFilesOrDirectories(partial_file_name, false, matches, Resolver);
513}
514
516 CompletionRequest &request,
517 SearchFilter *searcher) {
518 DiskFilesOrDirectories(request, /*only_dirs*/ true);
519}
520
521void CommandCompletions::DiskDirectories(const llvm::Twine &partial_file_name,
522 StringList &matches,
523 TildeExpressionResolver &Resolver) {
524 DiskFilesOrDirectories(partial_file_name, true, matches, Resolver);
525}
526
528 CompletionRequest &request,
529 SearchFilter *searcher) {
530 lldb::PlatformSP platform_sp =
532 if (platform_sp)
533 platform_sp->AutoCompleteDiskFileOrDirectory(request, false);
534}
535
537 CompletionRequest &request,
538 SearchFilter *searcher) {
539 lldb::PlatformSP platform_sp =
541 if (platform_sp)
542 platform_sp->AutoCompleteDiskFileOrDirectory(request, true);
543}
544
546 CompletionRequest &request,
547 SearchFilter *searcher) {
548 ModuleCompleter completer(interpreter, request);
549
550 if (searcher == nullptr) {
551 lldb::TargetSP target_sp = interpreter.GetSelectedTarget();
552 SearchFilterForUnconstrainedSearches null_searcher(target_sp);
553 completer.DoCompletion(&null_searcher);
554 } else {
555 completer.DoCompletion(searcher);
556 }
557}
558
560 CompletionRequest &request,
561 SearchFilter *searcher) {
562 const ExecutionContext &exe_ctx = interpreter.GetExecutionContext();
563 if (!exe_ctx.HasTargetScope())
564 return;
565
566 exe_ctx.GetTargetPtr()->GetImages().ForEach(
567 [&request](const lldb::ModuleSP &module) {
568 StreamString strm;
569 module->GetDescription(strm.AsRawOstream(),
570 lldb::eDescriptionLevelInitial);
571 request.TryCompleteCurrentArg(module->GetUUID().GetAsString(),
572 strm.GetString());
574 });
575}
576
578 CompletionRequest &request,
579 SearchFilter *searcher) {
580 SymbolCompleter completer(interpreter, request);
581
582 if (searcher == nullptr) {
583 lldb::TargetSP target_sp = interpreter.GetSelectedTarget();
584 SearchFilterForUnconstrainedSearches null_searcher(target_sp);
585 completer.DoCompletion(&null_searcher);
586 } else {
587 completer.DoCompletion(searcher);
588 }
589}
590
592 CompletionRequest &request,
593 SearchFilter *searcher) {
594 // Cache the full setting name/description list.
595 static StringList g_property_names;
596 static StringList g_property_descriptions;
597 if (g_property_names.GetSize() == 0) {
598 // Generate the full setting name list on demand
599 lldb::OptionValuePropertiesSP properties_sp(
600 interpreter.GetDebugger().GetValueProperties());
601 if (properties_sp) {
602 StreamString strm;
603 properties_sp->DumpValue(nullptr, strm, OptionValue::eDumpOptionName);
604 const std::string &str = std::string(strm.GetString());
605 g_property_names.SplitIntoLines(str.c_str(), str.size());
606
607 // Look up the description for each setting name so it can be displayed
608 // alongside the completion.
609 for (const std::string &name : g_property_names) {
610 std::string description;
611 if (const Property *property =
612 properties_sp->GetPropertyAtPath(nullptr, name))
613 description = property->GetDescription().str();
614 g_property_descriptions.AppendString(description);
615 }
616 }
617 }
618
619 assert(g_property_names.GetSize() == g_property_descriptions.GetSize() &&
620 "Not all properties got descriptions?");
621 for (size_t i = 0; i < g_property_names.GetSize(); ++i)
622 request.TryCompleteCurrentArg(g_property_names[i],
623 g_property_descriptions[i]);
624}
625
632
634 CompletionRequest &request,
635 SearchFilter *searcher) {
636 ArchSpec::AutoComplete(request);
637}
638
640 CompletionRequest &request,
641 SearchFilter *searcher) {
642 Variable::AutoComplete(interpreter.GetExecutionContext(), request);
643}
644
646 CompletionRequest &request,
647 SearchFilter *searcher) {
648 std::string reg_prefix;
649 if (request.GetCursorArgumentPrefix().starts_with("$"))
650 reg_prefix = "$";
651
652 RegisterContext *reg_ctx =
654 if (!reg_ctx)
655 return;
656
657 const size_t reg_num = reg_ctx->GetRegisterCount();
658 for (size_t reg_idx = 0; reg_idx < reg_num; ++reg_idx) {
659 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_idx);
660 request.TryCompleteCurrentArg(reg_prefix + reg_info->name,
661 reg_info->alt_name);
662 }
663}
664
666 CompletionRequest &request,
667 SearchFilter *searcher) {
668 lldb::TargetSP target = interpreter.GetSelectedTarget();
669 if (!target)
670 return;
671
672 const BreakpointList &breakpoints = target->GetBreakpointList();
673
674 std::unique_lock<std::recursive_mutex> lock;
675 target->GetBreakpointList().GetListMutex(lock);
676
677 size_t num_breakpoints = breakpoints.GetSize();
678 if (num_breakpoints == 0)
679 return;
680
681 for (size_t i = 0; i < num_breakpoints; ++i) {
682 lldb::BreakpointSP bp = breakpoints.GetBreakpointAtIndex(i);
683
684 StreamString s;
685 bp->GetDescription(&s, lldb::eDescriptionLevelBrief);
686 llvm::StringRef bp_info = s.GetString();
687
688 const size_t colon_pos = bp_info.find_first_of(':');
689 if (colon_pos != llvm::StringRef::npos)
690 bp_info = bp_info.drop_front(colon_pos + 2);
691
692 request.TryCompleteCurrentArg(std::to_string(bp->GetID()), bp_info);
693 }
694}
695
697 CompletionRequest &request,
698 SearchFilter *searcher) {
699 lldb::TargetSP target = interpreter.GetSelectedTarget();
700 if (!target)
701 return;
702
703 std::vector<std::string> name_list;
704 target->GetBreakpointNames(name_list);
705
706 for (const std::string &name : name_list)
707 request.TryCompleteCurrentArg(name);
708}
709
717 CompletionRequest &request,
718 SearchFilter *searcher) {
719 // Currently the only valid options for disassemble -F are default, and for
720 // Intel architectures, att and intel.
721 static const char *flavors[] = {"default", "att", "intel"};
722 for (const char *flavor : flavors) {
723 request.TryCompleteCurrentArg(flavor);
724 }
725}
726
728 CompletionRequest &request,
729 SearchFilter *searcher) {
730 lldb::PlatformSP platform_sp(interpreter.GetPlatform(true));
731 if (!platform_sp)
732 return;
733 ProcessInstanceInfoList process_infos;
734 ProcessInstanceInfoMatch match_info;
735 platform_sp->FindProcesses(match_info, process_infos);
736 for (const ProcessInstanceInfo &info : process_infos)
737 request.TryCompleteCurrentArg(std::to_string(info.GetProcessID()),
738 info.GetName());
739}
740
742 CompletionRequest &request,
743 SearchFilter *searcher) {
744 lldb::PlatformSP platform_sp(interpreter.GetPlatform(true));
745 if (!platform_sp)
746 return;
747 ProcessInstanceInfoList process_infos;
748 ProcessInstanceInfoMatch match_info;
749 platform_sp->FindProcesses(match_info, process_infos);
750 for (const ProcessInstanceInfo &info : process_infos)
751 request.TryCompleteCurrentArg(info.GetName());
752}
753
755 CompletionRequest &request,
756 SearchFilter *searcher) {
757 for (int bit :
758 Language::GetLanguagesSupportingTypeSystems().bitvector.set_bits()) {
759 request.TryCompleteCurrentArg(
761 }
762}
763
765 CompletionRequest &request,
766 SearchFilter *searcher) {
767 const ExecutionContext &exe_ctx = interpreter.GetExecutionContext();
768 if (!exe_ctx.HasProcessScope())
769 return;
770
771 lldb::ThreadSP thread_sp = exe_ctx.GetThreadSP();
772 Debugger &dbg = interpreter.GetDebugger();
773 const uint32_t frame_num = thread_sp->GetStackFrameCount();
774 for (uint32_t i = 0; i < frame_num; ++i) {
775 lldb::StackFrameSP frame_sp = thread_sp->GetStackFrameAtIndex(i);
776 StreamString strm;
777 // Dumping frames can be slow, allow interruption.
778 if (INTERRUPT_REQUESTED(dbg, "Interrupted in frame completion"))
779 break;
780 frame_sp->Dump(&strm, false, true);
781 request.TryCompleteCurrentArg(std::to_string(i), strm.GetString());
782 }
783}
784
786 CompletionRequest &request,
787 SearchFilter *searcher) {
788 const lldb::TargetSP target_sp =
789 interpreter.GetExecutionContext().GetTargetSP();
790 if (!target_sp)
791 return;
792
793 for (auto &stophook_sp : target_sp->GetStopHooks()) {
794 StreamString strm;
795 // The value 11 is an offset to make the completion description looks
796 // neater.
797 strm.SetIndentLevel(11);
798 stophook_sp->GetDescription(strm, lldb::eDescriptionLevelInitial);
799 request.TryCompleteCurrentArg(std::to_string(stophook_sp->GetID()),
800 strm.GetString());
801 }
802}
803
805 CompletionRequest &request,
806 SearchFilter *searcher) {
807 const ExecutionContext &exe_ctx = interpreter.GetExecutionContext();
808 if (!exe_ctx.HasProcessScope())
809 return;
810
811 ThreadList &threads = exe_ctx.GetProcessPtr()->GetThreadList();
812 lldb::ThreadSP thread_sp;
813 for (uint32_t idx = 0; (thread_sp = threads.GetThreadAtIndex(idx)); ++idx) {
814 StreamString strm;
815 thread_sp->GetStatus(strm, 0, 1, 1, true, /*show_hidden*/ true);
816 request.TryCompleteCurrentArg(std::to_string(thread_sp->GetIndexID()),
817 strm.GetString());
818 }
819}
820
822 CompletionRequest &request,
823 SearchFilter *searcher) {
824 const ExecutionContext &exe_ctx = interpreter.GetExecutionContext();
825 if (!exe_ctx.HasTargetScope())
826 return;
827
828 const WatchpointList &wp_list = exe_ctx.GetTargetPtr()->GetWatchpointList();
829 for (lldb::WatchpointSP wp_sp : wp_list.Watchpoints()) {
830 StreamString strm;
831 wp_sp->Dump(&strm);
832 request.TryCompleteCurrentArg(std::to_string(wp_sp->GetID()),
833 strm.GetString());
834 }
835}
836
838 CompletionRequest &request,
839 SearchFilter *searcher) {
841 [&request](const lldb::TypeCategoryImplSP &category_sp) {
842 request.TryCompleteCurrentArg(category_sp->GetName(),
843 category_sp->GetDescription());
844 return true;
845 });
846}
847
849 CompletionRequest &request,
850 SearchFilter *searcher) {
851 const ExecutionContext &exe_ctx = interpreter.GetExecutionContext();
852 if (!exe_ctx.HasProcessScope())
853 return;
854
855 ThreadList &threads = exe_ctx.GetProcessPtr()->GetThreadList();
856 lldb::ThreadSP thread_sp;
857 for (uint32_t idx = 0; (thread_sp = threads.GetThreadAtIndex(idx)); ++idx) {
858 StreamString strm;
859 thread_sp->GetStatus(strm, 0, 1, 1, true, /*show_hidden*/ true);
860 request.TryCompleteCurrentArg(std::to_string(thread_sp->GetID()),
861 strm.GetString());
862 }
863}
864
871
873 CommandInterpreter &interpreter, CompletionRequest &request,
874 OptionElementVector &opt_element_vector) {
875 // The only arguments constitute a command path, however, there might be
876 // options interspersed among the arguments, and we need to skip those. Do that
877 // by copying the args vector, and just dropping all the option bits:
878 Args args = request.GetParsedLine();
879 std::vector<size_t> to_delete;
880 for (auto &elem : opt_element_vector) {
881 to_delete.push_back(elem.opt_pos);
882 if (elem.opt_arg_pos != 0)
883 to_delete.push_back(elem.opt_arg_pos);
884 }
885 sort(to_delete.begin(), to_delete.end(), std::greater<size_t>());
886 for (size_t idx : to_delete)
887 args.DeleteArgumentAtIndex(idx);
888
889 // At this point, we should only have args, so now lookup the command up to
890 // the cursor element.
891
892 // There's nothing here but options. It doesn't seem very useful here to
893 // dump all the commands, so just return.
894 size_t num_args = args.GetArgumentCount();
895 if (num_args == 0)
896 return;
897
898 // There's just one argument, so we should complete its name:
899 StringList matches;
900 if (num_args == 1) {
901 interpreter.GetUserCommandObject(args.GetArgumentAtIndex(0), &matches,
902 nullptr);
903 request.AddCompletions(matches);
904 return;
905 }
906
907 // There was more than one path element, lets find the containing command:
910 interpreter.VerifyUserMultiwordCmdPath(args, true, error);
911
912 // Something was wrong somewhere along the path, but I don't think there's
913 // a good way to go back and fill in the missing elements:
914 if (error.Fail())
915 return;
916
917 // This should never happen. We already handled the case of one argument
918 // above, and we can only get Success & nullptr back if there's a one-word
919 // leaf.
920 assert(mwc != nullptr);
921
922 mwc->GetSubcommandObject(args.GetArgumentAtIndex(num_args - 1), &matches);
923 if (matches.GetSize() == 0)
924 return;
925
926 request.AddCompletions(matches);
927}
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)
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 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:1243
WatchpointList & GetWatchpointList()
Definition Target.h:955
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:765
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
@ 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