1 //===-- CommandObjectType.cpp ---------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "CommandObjectType.h"
11 #include "lldb/Core/Debugger.h"
12 #include "lldb/Core/IOHandler.h"
13 #include "lldb/DataFormatters/DataVisualization.h"
14 #include "lldb/Host/Config.h"
15 #include "lldb/Host/OptionParser.h"
16 #include "lldb/Interpreter/CommandInterpreter.h"
17 #include "lldb/Interpreter/CommandObject.h"
18 #include "lldb/Interpreter/CommandReturnObject.h"
19 #include "lldb/Interpreter/OptionArgParser.h"
20 #include "lldb/Interpreter/OptionGroupFormat.h"
21 #include "lldb/Interpreter/OptionValueBoolean.h"
22 #include "lldb/Interpreter/OptionValueLanguage.h"
23 #include "lldb/Interpreter/OptionValueString.h"
24 #include "lldb/Interpreter/Options.h"
25 #include "lldb/Symbol/Symbol.h"
26 #include "lldb/Target/Language.h"
27 #include "lldb/Target/StackFrame.h"
28 #include "lldb/Target/Target.h"
29 #include "lldb/Target/Thread.h"
30 #include "lldb/Utility/ConstString.h"
31 #include "lldb/Utility/RegularExpression.h"
32 #include "lldb/Utility/StringList.h"
34 #include "llvm/ADT/STLExtras.h"
40 #define CHECK_FORMATTER_KIND_MASK(VAL) \
41 ((m_formatter_kind_mask & (VAL)) == (VAL))
44 using namespace lldb_private;
46 class ScriptAddOptions {
48 TypeSummaryImpl::Flags m_flags;
49 StringList m_target_types;
52 std::string m_category;
54 ScriptAddOptions(const TypeSummaryImpl::Flags &flags, bool regx,
55 ConstString name, std::string catg)
56 : m_flags(flags), m_regex(regx), m_name(name), m_category(catg) {}
58 typedef std::shared_ptr<ScriptAddOptions> SharedPointer;
61 class SynthAddOptions {
64 bool m_skip_references;
67 StringList m_target_types;
68 std::string m_category;
70 SynthAddOptions(bool sptr, bool sref, bool casc, bool regx, std::string catg)
71 : m_skip_pointers(sptr), m_skip_references(sref), m_cascade(casc),
72 m_regex(regx), m_target_types(), m_category(catg) {}
74 typedef std::shared_ptr<SynthAddOptions> SharedPointer;
77 static bool WarnOnPotentialUnquotedUnsignedType(Args &command,
78 CommandReturnObject &result) {
82 for (auto entry : llvm::enumerate(command.entries().drop_back())) {
83 if (entry.value().ref() != "unsigned")
85 auto next = command.entries()[entry.index() + 1].ref();
86 if (next == "int" || next == "short" || next == "char" || next == "long") {
87 result.AppendWarningWithFormat(
88 "unsigned %s being treated as two types. if you meant the combined "
90 "name use quotes, as in \"unsigned %s\"\n",
91 next.str().c_str(), next.str().c_str());
98 #define LLDB_OPTIONS_type_summary_add
99 #include "CommandOptions.inc"
101 class CommandObjectTypeSummaryAdd : public CommandObjectParsed,
102 public IOHandlerDelegateMultiline {
104 class CommandOptions : public Options {
106 CommandOptions(CommandInterpreter &interpreter) : Options() {}
108 ~CommandOptions() override = default;
110 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
111 ExecutionContext *execution_context) override;
113 void OptionParsingStarting(ExecutionContext *execution_context) override;
115 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
116 return llvm::makeArrayRef(g_type_summary_add_options);
119 // Instance variables to hold the values for command options.
121 TypeSummaryImpl::Flags m_flags;
123 std::string m_format_string;
125 std::string m_python_script;
126 std::string m_python_function;
127 bool m_is_add_script;
128 std::string m_category;
131 CommandOptions m_options;
133 Options *GetOptions() override { return &m_options; }
135 bool Execute_ScriptSummary(Args &command, CommandReturnObject &result);
137 bool Execute_StringSummary(Args &command, CommandReturnObject &result);
140 enum SummaryFormatType { eRegularSummary, eRegexSummary, eNamedSummary };
142 CommandObjectTypeSummaryAdd(CommandInterpreter &interpreter);
144 ~CommandObjectTypeSummaryAdd() override = default;
146 void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
147 static const char *g_summary_addreader_instructions =
148 "Enter your Python command(s). Type 'DONE' to end.\n"
149 "def function (valobj,internal_dict):\n"
150 " \"\"\"valobj: an SBValue which you want to provide a summary "
152 " internal_dict: an LLDB support object not to be used\"\"\"\n";
154 StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
155 if (output_sp && interactive) {
156 output_sp->PutCString(g_summary_addreader_instructions);
161 void IOHandlerInputComplete(IOHandler &io_handler,
162 std::string &data) override {
163 StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
165 #if LLDB_ENABLE_PYTHON
166 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
169 lines.SplitIntoLines(data);
170 if (lines.GetSize() > 0) {
171 ScriptAddOptions *options_ptr =
172 ((ScriptAddOptions *)io_handler.GetUserData());
174 ScriptAddOptions::SharedPointer options(
175 options_ptr); // this will ensure that we get rid of the pointer
176 // when going out of scope
178 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
180 std::string funct_name_str;
181 if (interpreter->GenerateTypeScriptFunction(lines,
183 if (funct_name_str.empty()) {
184 error_sp->Printf("unable to obtain a valid function name from "
185 "the script interpreter.\n");
188 // now I have a valid function name, let's add this as script
189 // for every type in the list
191 TypeSummaryImplSP script_format;
192 script_format = std::make_shared<ScriptSummaryFormat>(
193 options->m_flags, funct_name_str.c_str(),
194 lines.CopyList(" ").c_str());
198 for (const std::string &type_name : options->m_target_types) {
199 CommandObjectTypeSummaryAdd::AddSummary(
200 ConstString(type_name), script_format,
202 ? CommandObjectTypeSummaryAdd::eRegexSummary
203 : CommandObjectTypeSummaryAdd::eRegularSummary),
204 options->m_category, &error);
206 error_sp->Printf("error: %s", error.AsCString());
211 if (options->m_name) {
212 CommandObjectTypeSummaryAdd::AddSummary(
213 options->m_name, script_format,
214 CommandObjectTypeSummaryAdd::eNamedSummary,
215 options->m_category, &error);
217 CommandObjectTypeSummaryAdd::AddSummary(
218 options->m_name, script_format,
219 CommandObjectTypeSummaryAdd::eNamedSummary,
220 options->m_category, &error);
222 error_sp->Printf("error: %s", error.AsCString());
226 error_sp->Printf("error: %s", error.AsCString());
230 if (error.AsCString()) {
231 error_sp->Printf("error: %s", error.AsCString());
237 error_sp->Printf("error: unable to generate a function.\n");
241 error_sp->Printf("error: no script interpreter.\n");
245 error_sp->Printf("error: internal synchronization information "
246 "missing or invalid.\n");
250 error_sp->Printf("error: empty function, didn't add python command.\n");
255 "error: script interpreter missing, didn't add python command.\n");
259 io_handler.SetIsDone(true);
262 static bool AddSummary(ConstString type_name, lldb::TypeSummaryImplSP entry,
263 SummaryFormatType type, std::string category,
264 Status *error = nullptr);
267 bool DoExecute(Args &command, CommandReturnObject &result) override;
270 static const char *g_synth_addreader_instructions =
271 "Enter your Python command(s). Type 'DONE' to end.\n"
272 "You must define a Python class with these methods:\n"
273 " def __init__(self, valobj, internal_dict):\n"
274 " def num_children(self):\n"
275 " def get_child_at_index(self, index):\n"
276 " def get_child_index(self, name):\n"
277 " def update(self):\n"
279 "class synthProvider:\n";
281 #define LLDB_OPTIONS_type_synth_add
282 #include "CommandOptions.inc"
284 class CommandObjectTypeSynthAdd : public CommandObjectParsed,
285 public IOHandlerDelegateMultiline {
287 class CommandOptions : public Options {
289 CommandOptions() : Options() {}
291 ~CommandOptions() override = default;
293 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
294 ExecutionContext *execution_context) override {
296 const int short_option = m_getopt_table[option_idx].val;
299 switch (short_option) {
301 m_cascade = OptionArgParser::ToBoolean(option_arg, true, &success);
303 error.SetErrorStringWithFormat("invalid value for cascade: %s",
304 option_arg.str().c_str());
307 handwrite_python = true;
310 m_class_name = std::string(option_arg);
311 is_class_based = true;
314 m_skip_pointers = true;
317 m_skip_references = true;
320 m_category = std::string(option_arg);
326 llvm_unreachable("Unimplemented option");
332 void OptionParsingStarting(ExecutionContext *execution_context) override {
335 m_skip_pointers = false;
336 m_skip_references = false;
337 m_category = "default";
338 is_class_based = false;
339 handwrite_python = false;
343 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
344 return llvm::makeArrayRef(g_type_synth_add_options);
347 // Instance variables to hold the values for command options.
350 bool m_skip_references;
351 bool m_skip_pointers;
352 std::string m_class_name;
354 std::string m_category;
356 bool handwrite_python;
360 CommandOptions m_options;
362 Options *GetOptions() override { return &m_options; }
364 bool Execute_HandwritePython(Args &command, CommandReturnObject &result);
366 bool Execute_PythonClass(Args &command, CommandReturnObject &result);
369 bool DoExecute(Args &command, CommandReturnObject &result) override {
370 WarnOnPotentialUnquotedUnsignedType(command, result);
372 if (m_options.handwrite_python)
373 return Execute_HandwritePython(command, result);
374 else if (m_options.is_class_based)
375 return Execute_PythonClass(command, result);
377 result.AppendError("must either provide a children list, a Python class "
378 "name, or use -P and type a Python class "
384 void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
385 StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
386 if (output_sp && interactive) {
387 output_sp->PutCString(g_synth_addreader_instructions);
392 void IOHandlerInputComplete(IOHandler &io_handler,
393 std::string &data) override {
394 StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
396 #if LLDB_ENABLE_PYTHON
397 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
400 lines.SplitIntoLines(data);
401 if (lines.GetSize() > 0) {
402 SynthAddOptions *options_ptr =
403 ((SynthAddOptions *)io_handler.GetUserData());
405 SynthAddOptions::SharedPointer options(
406 options_ptr); // this will ensure that we get rid of the pointer
407 // when going out of scope
409 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
411 std::string class_name_str;
412 if (interpreter->GenerateTypeSynthClass(lines, class_name_str)) {
413 if (class_name_str.empty()) {
415 "error: unable to obtain a proper name for the class.\n");
418 // everything should be fine now, let's add the synth provider
421 SyntheticChildrenSP synth_provider;
422 synth_provider = std::make_shared<ScriptedSyntheticChildren>(
423 SyntheticChildren::Flags()
424 .SetCascades(options->m_cascade)
425 .SetSkipPointers(options->m_skip_pointers)
426 .SetSkipReferences(options->m_skip_references),
427 class_name_str.c_str());
429 lldb::TypeCategoryImplSP category;
430 DataVisualization::Categories::GetCategory(
431 ConstString(options->m_category.c_str()), category);
435 for (const std::string &type_name : options->m_target_types) {
436 if (!type_name.empty()) {
437 if (!CommandObjectTypeSynthAdd::AddSynth(
438 ConstString(type_name), synth_provider,
440 ? CommandObjectTypeSynthAdd::eRegexSynth
441 : CommandObjectTypeSynthAdd::eRegularSynth,
442 options->m_category, &error)) {
443 error_sp->Printf("error: %s\n", error.AsCString());
448 error_sp->Printf("error: invalid type name.\n");
455 error_sp->Printf("error: unable to generate a class.\n");
459 error_sp->Printf("error: no script interpreter.\n");
463 error_sp->Printf("error: internal synchronization data missing.\n");
467 error_sp->Printf("error: empty function, didn't add python command.\n");
472 "error: script interpreter missing, didn't add python command.\n");
477 io_handler.SetIsDone(true);
481 enum SynthFormatType { eRegularSynth, eRegexSynth };
483 CommandObjectTypeSynthAdd(CommandInterpreter &interpreter);
485 ~CommandObjectTypeSynthAdd() override = default;
487 static bool AddSynth(ConstString type_name, lldb::SyntheticChildrenSP entry,
488 SynthFormatType type, std::string category_name,
492 // CommandObjectTypeFormatAdd
494 #define LLDB_OPTIONS_type_format_add
495 #include "CommandOptions.inc"
497 class CommandObjectTypeFormatAdd : public CommandObjectParsed {
499 class CommandOptions : public OptionGroup {
501 CommandOptions() : OptionGroup() {}
503 ~CommandOptions() override = default;
505 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
506 return llvm::makeArrayRef(g_type_format_add_options);
509 void OptionParsingStarting(ExecutionContext *execution_context) override {
511 m_skip_pointers = false;
512 m_skip_references = false;
514 m_category.assign("default");
515 m_custom_type_name.clear();
518 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
519 ExecutionContext *execution_context) override {
521 const int short_option =
522 g_type_format_add_options[option_idx].short_option;
525 switch (short_option) {
527 m_cascade = OptionArgParser::ToBoolean(option_value, true, &success);
529 error.SetErrorStringWithFormat("invalid value for cascade: %s",
530 option_value.str().c_str());
533 m_skip_pointers = true;
536 m_category.assign(std::string(option_value));
539 m_skip_references = true;
545 m_custom_type_name.assign(std::string(option_value));
548 llvm_unreachable("Unimplemented option");
554 // Instance variables to hold the values for command options.
557 bool m_skip_references;
558 bool m_skip_pointers;
560 std::string m_category;
561 std::string m_custom_type_name;
564 OptionGroupOptions m_option_group;
565 OptionGroupFormat m_format_options;
566 CommandOptions m_command_options;
568 Options *GetOptions() override { return &m_option_group; }
571 CommandObjectTypeFormatAdd(CommandInterpreter &interpreter)
572 : CommandObjectParsed(interpreter, "type format add",
573 "Add a new formatting style for a type.", nullptr),
574 m_option_group(), m_format_options(eFormatInvalid),
575 m_command_options() {
576 CommandArgumentEntry type_arg;
577 CommandArgumentData type_style_arg;
579 type_style_arg.arg_type = eArgTypeName;
580 type_style_arg.arg_repetition = eArgRepeatPlus;
582 type_arg.push_back(type_style_arg);
584 m_arguments.push_back(type_arg);
588 The following examples of 'type format add' refer to this code snippet for context:
591 typedef float Afloat;
593 typedef Afloat Bfloat;
601 Adding default formatting:
603 (lldb) type format add -f hex AInt
604 (lldb) frame variable iy
607 " Produces hexadecimal display of iy, because no formatter is available for Bint and \
608 the one for Aint is used instead."
611 To prevent this use the cascade option '-C no' to prevent evaluation of typedef chains:
614 (lldb) type format add -f hex -C no AInt
616 Similar reasoning applies to this:
618 (lldb) type format add -f hex -C no float -p
621 " All float values and float references are now formatted as hexadecimal, but not \
622 pointers to floats. Nor will it change the default display for Afloat and Bfloat objects.");
624 // Add the "--format" to all options groups
625 m_option_group.Append(&m_format_options,
626 OptionGroupFormat::OPTION_GROUP_FORMAT,
628 m_option_group.Append(&m_command_options);
629 m_option_group.Finalize();
632 ~CommandObjectTypeFormatAdd() override = default;
635 bool DoExecute(Args &command, CommandReturnObject &result) override {
636 const size_t argc = command.GetArgumentCount();
639 result.AppendErrorWithFormat("%s takes one or more args.\n",
644 const Format format = m_format_options.GetFormat();
645 if (format == eFormatInvalid &&
646 m_command_options.m_custom_type_name.empty()) {
647 result.AppendErrorWithFormat("%s needs a valid format.\n",
652 TypeFormatImplSP entry;
654 if (m_command_options.m_custom_type_name.empty())
655 entry = std::make_shared<TypeFormatImpl_Format>(
656 format, TypeFormatImpl::Flags()
657 .SetCascades(m_command_options.m_cascade)
658 .SetSkipPointers(m_command_options.m_skip_pointers)
659 .SetSkipReferences(m_command_options.m_skip_references));
661 entry = std::make_shared<TypeFormatImpl_EnumType>(
662 ConstString(m_command_options.m_custom_type_name.c_str()),
663 TypeFormatImpl::Flags()
664 .SetCascades(m_command_options.m_cascade)
665 .SetSkipPointers(m_command_options.m_skip_pointers)
666 .SetSkipReferences(m_command_options.m_skip_references));
668 // now I have a valid format, let's add it to every type
670 TypeCategoryImplSP category_sp;
671 DataVisualization::Categories::GetCategory(
672 ConstString(m_command_options.m_category), category_sp);
676 WarnOnPotentialUnquotedUnsignedType(command, result);
678 for (auto &arg_entry : command.entries()) {
679 if (arg_entry.ref().empty()) {
680 result.AppendError("empty typenames not allowed");
684 ConstString typeCS(arg_entry.ref());
685 if (m_command_options.m_regex) {
686 RegularExpression typeRX(arg_entry.ref());
687 if (!typeRX.IsValid()) {
689 "regex format error (maybe this is not really a regex?)");
692 category_sp->GetRegexTypeSummariesContainer()->Delete(typeCS);
693 category_sp->GetRegexTypeFormatsContainer()->Add(std::move(typeRX),
696 category_sp->GetTypeFormatsContainer()->Add(std::move(typeCS), entry);
699 result.SetStatus(eReturnStatusSuccessFinishNoResult);
700 return result.Succeeded();
704 #define LLDB_OPTIONS_type_formatter_delete
705 #include "CommandOptions.inc"
707 class CommandObjectTypeFormatterDelete : public CommandObjectParsed {
709 class CommandOptions : public Options {
711 CommandOptions() : Options() {}
713 ~CommandOptions() override = default;
715 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
716 ExecutionContext *execution_context) override {
718 const int short_option = m_getopt_table[option_idx].val;
720 switch (short_option) {
725 m_category = std::string(option_arg);
728 m_language = Language::GetLanguageTypeFromString(option_arg);
731 llvm_unreachable("Unimplemented option");
737 void OptionParsingStarting(ExecutionContext *execution_context) override {
738 m_delete_all = false;
739 m_category = "default";
740 m_language = lldb::eLanguageTypeUnknown;
743 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
744 return llvm::makeArrayRef(g_type_formatter_delete_options);
747 // Instance variables to hold the values for command options.
750 std::string m_category;
751 lldb::LanguageType m_language;
754 CommandOptions m_options;
755 uint32_t m_formatter_kind_mask;
757 Options *GetOptions() override { return &m_options; }
760 CommandObjectTypeFormatterDelete(CommandInterpreter &interpreter,
761 uint32_t formatter_kind_mask,
762 const char *name, const char *help)
763 : CommandObjectParsed(interpreter, name, help, nullptr), m_options(),
764 m_formatter_kind_mask(formatter_kind_mask) {
765 CommandArgumentEntry type_arg;
766 CommandArgumentData type_style_arg;
768 type_style_arg.arg_type = eArgTypeName;
769 type_style_arg.arg_repetition = eArgRepeatPlain;
771 type_arg.push_back(type_style_arg);
773 m_arguments.push_back(type_arg);
776 ~CommandObjectTypeFormatterDelete() override = default;
779 HandleArgumentCompletion(CompletionRequest &request,
780 OptionElementVector &opt_element_vector) override {
781 if (request.GetCursorIndex())
784 DataVisualization::Categories::ForEach(
785 [this, &request](const lldb::TypeCategoryImplSP &category_sp) {
786 if (CHECK_FORMATTER_KIND_MASK(eFormatCategoryItemValue))
787 category_sp->GetTypeFormatsContainer()->AutoComplete(request);
788 if (CHECK_FORMATTER_KIND_MASK(eFormatCategoryItemRegexValue))
789 category_sp->GetRegexTypeFormatsContainer()->AutoComplete(request);
791 if (CHECK_FORMATTER_KIND_MASK(eFormatCategoryItemSummary))
792 category_sp->GetTypeSummariesContainer()->AutoComplete(request);
793 if (CHECK_FORMATTER_KIND_MASK(eFormatCategoryItemRegexSummary))
794 category_sp->GetRegexTypeSummariesContainer()->AutoComplete(
797 if (CHECK_FORMATTER_KIND_MASK(eFormatCategoryItemFilter))
798 category_sp->GetTypeFiltersContainer()->AutoComplete(request);
799 if (CHECK_FORMATTER_KIND_MASK(eFormatCategoryItemRegexFilter))
800 category_sp->GetRegexTypeFiltersContainer()->AutoComplete(request);
802 if (CHECK_FORMATTER_KIND_MASK(eFormatCategoryItemSynth))
803 category_sp->GetTypeSyntheticsContainer()->AutoComplete(request);
804 if (CHECK_FORMATTER_KIND_MASK(eFormatCategoryItemRegexSynth))
805 category_sp->GetRegexTypeSyntheticsContainer()->AutoComplete(
812 virtual bool FormatterSpecificDeletion(ConstString typeCS) { return false; }
814 bool DoExecute(Args &command, CommandReturnObject &result) override {
815 const size_t argc = command.GetArgumentCount();
818 result.AppendErrorWithFormat("%s takes 1 arg.\n", m_cmd_name.c_str());
822 const char *typeA = command.GetArgumentAtIndex(0);
823 ConstString typeCS(typeA);
826 result.AppendError("empty typenames not allowed");
830 if (m_options.m_delete_all) {
831 DataVisualization::Categories::ForEach(
832 [this, typeCS](const lldb::TypeCategoryImplSP &category_sp) -> bool {
833 category_sp->Delete(typeCS, m_formatter_kind_mask);
836 result.SetStatus(eReturnStatusSuccessFinishNoResult);
837 return result.Succeeded();
840 bool delete_category = false;
841 bool extra_deletion = false;
843 if (m_options.m_language != lldb::eLanguageTypeUnknown) {
844 lldb::TypeCategoryImplSP category;
845 DataVisualization::Categories::GetCategory(m_options.m_language,
848 delete_category = category->Delete(typeCS, m_formatter_kind_mask);
849 extra_deletion = FormatterSpecificDeletion(typeCS);
851 lldb::TypeCategoryImplSP category;
852 DataVisualization::Categories::GetCategory(
853 ConstString(m_options.m_category.c_str()), category);
855 delete_category = category->Delete(typeCS, m_formatter_kind_mask);
856 extra_deletion = FormatterSpecificDeletion(typeCS);
859 if (delete_category || extra_deletion) {
860 result.SetStatus(eReturnStatusSuccessFinishNoResult);
861 return result.Succeeded();
863 result.AppendErrorWithFormat("no custom formatter for %s.\n", typeA);
869 #define LLDB_OPTIONS_type_formatter_clear
870 #include "CommandOptions.inc"
872 class CommandObjectTypeFormatterClear : public CommandObjectParsed {
874 class CommandOptions : public Options {
876 CommandOptions() : Options() {}
878 ~CommandOptions() override = default;
880 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
881 ExecutionContext *execution_context) override {
883 const int short_option = m_getopt_table[option_idx].val;
885 switch (short_option) {
890 llvm_unreachable("Unimplemented option");
896 void OptionParsingStarting(ExecutionContext *execution_context) override {
897 m_delete_all = false;
900 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
901 return llvm::makeArrayRef(g_type_formatter_clear_options);
904 // Instance variables to hold the values for command options.
908 CommandOptions m_options;
909 uint32_t m_formatter_kind_mask;
911 Options *GetOptions() override { return &m_options; }
914 CommandObjectTypeFormatterClear(CommandInterpreter &interpreter,
915 uint32_t formatter_kind_mask,
916 const char *name, const char *help)
917 : CommandObjectParsed(interpreter, name, help, nullptr), m_options(),
918 m_formatter_kind_mask(formatter_kind_mask) {}
920 ~CommandObjectTypeFormatterClear() override = default;
923 virtual void FormatterSpecificDeletion() {}
925 bool DoExecute(Args &command, CommandReturnObject &result) override {
926 if (m_options.m_delete_all) {
927 DataVisualization::Categories::ForEach(
928 [this](const TypeCategoryImplSP &category_sp) -> bool {
929 category_sp->Clear(m_formatter_kind_mask);
933 lldb::TypeCategoryImplSP category;
934 if (command.GetArgumentCount() > 0) {
935 const char *cat_name = command.GetArgumentAtIndex(0);
936 ConstString cat_nameCS(cat_name);
937 DataVisualization::Categories::GetCategory(cat_nameCS, category);
939 DataVisualization::Categories::GetCategory(ConstString(nullptr),
942 category->Clear(m_formatter_kind_mask);
945 FormatterSpecificDeletion();
947 result.SetStatus(eReturnStatusSuccessFinishResult);
948 return result.Succeeded();
952 // CommandObjectTypeFormatDelete
954 class CommandObjectTypeFormatDelete : public CommandObjectTypeFormatterDelete {
956 CommandObjectTypeFormatDelete(CommandInterpreter &interpreter)
957 : CommandObjectTypeFormatterDelete(
959 eFormatCategoryItemValue | eFormatCategoryItemRegexValue,
960 "type format delete",
961 "Delete an existing formatting style for a type.") {}
963 ~CommandObjectTypeFormatDelete() override = default;
966 // CommandObjectTypeFormatClear
968 class CommandObjectTypeFormatClear : public CommandObjectTypeFormatterClear {
970 CommandObjectTypeFormatClear(CommandInterpreter &interpreter)
971 : CommandObjectTypeFormatterClear(
973 eFormatCategoryItemValue | eFormatCategoryItemRegexValue,
974 "type format clear", "Delete all existing format styles.") {}
977 #define LLDB_OPTIONS_type_formatter_list
978 #include "CommandOptions.inc"
980 template <typename FormatterType>
981 class CommandObjectTypeFormatterList : public CommandObjectParsed {
982 typedef typename FormatterType::SharedPointer FormatterSharedPointer;
984 class CommandOptions : public Options {
987 : Options(), m_category_regex("", ""),
988 m_category_language(lldb::eLanguageTypeUnknown,
989 lldb::eLanguageTypeUnknown) {}
991 ~CommandOptions() override = default;
993 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
994 ExecutionContext *execution_context) override {
996 const int short_option = m_getopt_table[option_idx].val;
997 switch (short_option) {
999 m_category_regex.SetCurrentValue(option_arg);
1000 m_category_regex.SetOptionWasSet();
1003 error = m_category_language.SetValueFromString(option_arg);
1004 if (error.Success())
1005 m_category_language.SetOptionWasSet();
1008 llvm_unreachable("Unimplemented option");
1014 void OptionParsingStarting(ExecutionContext *execution_context) override {
1015 m_category_regex.Clear();
1016 m_category_language.Clear();
1019 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1020 return llvm::makeArrayRef(g_type_formatter_list_options);
1023 // Instance variables to hold the values for command options.
1025 OptionValueString m_category_regex;
1026 OptionValueLanguage m_category_language;
1029 CommandOptions m_options;
1031 Options *GetOptions() override { return &m_options; }
1034 CommandObjectTypeFormatterList(CommandInterpreter &interpreter,
1035 const char *name, const char *help)
1036 : CommandObjectParsed(interpreter, name, help, nullptr), m_options() {
1037 CommandArgumentEntry type_arg;
1038 CommandArgumentData type_style_arg;
1040 type_style_arg.arg_type = eArgTypeName;
1041 type_style_arg.arg_repetition = eArgRepeatOptional;
1043 type_arg.push_back(type_style_arg);
1045 m_arguments.push_back(type_arg);
1048 ~CommandObjectTypeFormatterList() override = default;
1051 virtual bool FormatterSpecificList(CommandReturnObject &result) {
1055 bool DoExecute(Args &command, CommandReturnObject &result) override {
1056 const size_t argc = command.GetArgumentCount();
1058 std::unique_ptr<RegularExpression> category_regex;
1059 std::unique_ptr<RegularExpression> formatter_regex;
1061 if (m_options.m_category_regex.OptionWasSet()) {
1062 category_regex = std::make_unique<RegularExpression>(
1063 m_options.m_category_regex.GetCurrentValueAsRef());
1064 if (!category_regex->IsValid()) {
1065 result.AppendErrorWithFormat(
1066 "syntax error in category regular expression '%s'",
1067 m_options.m_category_regex.GetCurrentValueAsRef().str().c_str());
1073 const char *arg = command.GetArgumentAtIndex(0);
1074 formatter_regex = std::make_unique<RegularExpression>(arg);
1075 if (!formatter_regex->IsValid()) {
1076 result.AppendErrorWithFormat("syntax error in regular expression '%s'",
1082 bool any_printed = false;
1084 auto category_closure =
1085 [&result, &formatter_regex,
1086 &any_printed](const lldb::TypeCategoryImplSP &category) -> void {
1087 result.GetOutputStream().Printf(
1088 "-----------------------\nCategory: %s%s\n-----------------------\n",
1089 category->GetName(), category->IsEnabled() ? "" : " (disabled)");
1091 TypeCategoryImpl::ForEachCallbacks<FormatterType> foreach;
1093 .SetExact([&result, &formatter_regex, &any_printed](
1094 const TypeMatcher &type_matcher,
1095 const FormatterSharedPointer &format_sp) -> bool {
1096 if (formatter_regex) {
1098 if (type_matcher.CreatedBySameMatchString(
1099 ConstString(formatter_regex->GetText()))) {
1101 } else if (formatter_regex->Execute(
1102 type_matcher.GetMatchString().GetStringRef())) {
1111 result.GetOutputStream().Printf(
1112 "%s: %s\n", type_matcher.GetMatchString().GetCString(),
1113 format_sp->GetDescription().c_str());
1118 .SetWithRegex([&result, &formatter_regex, &any_printed](
1119 const TypeMatcher &type_matcher,
1120 const FormatterSharedPointer &format_sp) -> bool {
1121 if (formatter_regex) {
1123 if (type_matcher.CreatedBySameMatchString(
1124 ConstString(formatter_regex->GetText()))) {
1126 } else if (formatter_regex->Execute(
1127 type_matcher.GetMatchString().GetStringRef())) {
1136 result.GetOutputStream().Printf(
1137 "%s: %s\n", type_matcher.GetMatchString().GetCString(),
1138 format_sp->GetDescription().c_str());
1142 category->ForEach(foreach);
1145 if (m_options.m_category_language.OptionWasSet()) {
1146 lldb::TypeCategoryImplSP category_sp;
1147 DataVisualization::Categories::GetCategory(
1148 m_options.m_category_language.GetCurrentValue(), category_sp);
1150 category_closure(category_sp);
1152 DataVisualization::Categories::ForEach(
1153 [&category_regex, &category_closure](
1154 const lldb::TypeCategoryImplSP &category) -> bool {
1155 if (category_regex) {
1157 if (category->GetName() == category_regex->GetText()) {
1159 } else if (category_regex->Execute(category->GetName())) {
1167 category_closure(category);
1172 any_printed = FormatterSpecificList(result) | any_printed;
1176 result.SetStatus(eReturnStatusSuccessFinishResult);
1178 result.GetOutputStream().PutCString("no matching results found.\n");
1179 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1181 return result.Succeeded();
1185 // CommandObjectTypeFormatList
1187 class CommandObjectTypeFormatList
1188 : public CommandObjectTypeFormatterList<TypeFormatImpl> {
1190 CommandObjectTypeFormatList(CommandInterpreter &interpreter)
1191 : CommandObjectTypeFormatterList(interpreter, "type format list",
1192 "Show a list of current formats.") {}
1195 Status CommandObjectTypeSummaryAdd::CommandOptions::SetOptionValue(
1196 uint32_t option_idx, llvm::StringRef option_arg,
1197 ExecutionContext *execution_context) {
1199 const int short_option = m_getopt_table[option_idx].val;
1202 switch (short_option) {
1204 m_flags.SetCascades(OptionArgParser::ToBoolean(option_arg, true, &success));
1206 error.SetErrorStringWithFormat("invalid value for cascade: %s",
1207 option_arg.str().c_str());
1210 m_flags.SetDontShowChildren(false);
1213 m_flags.SetHideEmptyAggregates(true);
1216 m_flags.SetDontShowValue(true);
1219 m_flags.SetShowMembersOneLiner(true);
1222 m_format_string = std::string(option_arg);
1225 m_flags.SetSkipPointers(true);
1228 m_flags.SetSkipReferences(true);
1234 m_name.SetString(option_arg);
1237 m_python_script = std::string(option_arg);
1238 m_is_add_script = true;
1241 m_python_function = std::string(option_arg);
1242 m_is_add_script = true;
1245 m_is_add_script = true;
1248 m_category = std::string(option_arg);
1251 m_flags.SetHideItemNames(true);
1254 llvm_unreachable("Unimplemented option");
1260 void CommandObjectTypeSummaryAdd::CommandOptions::OptionParsingStarting(
1261 ExecutionContext *execution_context) {
1262 m_flags.Clear().SetCascades().SetDontShowChildren().SetDontShowValue(false);
1263 m_flags.SetShowMembersOneLiner(false)
1264 .SetSkipPointers(false)
1265 .SetSkipReferences(false)
1266 .SetHideItemNames(false);
1270 m_python_script = "";
1271 m_python_function = "";
1272 m_format_string = "";
1273 m_is_add_script = false;
1274 m_category = "default";
1277 #if LLDB_ENABLE_PYTHON
1279 bool CommandObjectTypeSummaryAdd::Execute_ScriptSummary(
1280 Args &command, CommandReturnObject &result) {
1281 const size_t argc = command.GetArgumentCount();
1283 if (argc < 1 && !m_options.m_name) {
1284 result.AppendErrorWithFormat("%s takes one or more args.\n",
1285 m_cmd_name.c_str());
1289 TypeSummaryImplSP script_format;
1291 if (!m_options.m_python_function
1292 .empty()) // we have a Python function ready to use
1294 const char *funct_name = m_options.m_python_function.c_str();
1295 if (!funct_name || !funct_name[0]) {
1296 result.AppendError("function name empty.\n");
1301 (" " + m_options.m_python_function + "(valobj,internal_dict)");
1303 script_format = std::make_shared<ScriptSummaryFormat>(
1304 m_options.m_flags, funct_name, code.c_str());
1306 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
1308 if (interpreter && !interpreter->CheckObjectExists(funct_name))
1309 result.AppendWarningWithFormat(
1310 "The provided function \"%s\" does not exist - "
1311 "please define it before attempting to use this summary.\n",
1313 } else if (!m_options.m_python_script
1314 .empty()) // we have a quick 1-line script, just use it
1316 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
1318 result.AppendError("script interpreter missing - unable to generate "
1319 "function wrapper.\n");
1322 StringList funct_sl;
1323 funct_sl << m_options.m_python_script.c_str();
1324 std::string funct_name_str;
1325 if (!interpreter->GenerateTypeScriptFunction(funct_sl, funct_name_str)) {
1326 result.AppendError("unable to generate function wrapper.\n");
1329 if (funct_name_str.empty()) {
1331 "script interpreter failed to generate a valid function name.\n");
1335 std::string code = " " + m_options.m_python_script;
1337 script_format = std::make_shared<ScriptSummaryFormat>(
1338 m_options.m_flags, funct_name_str.c_str(), code.c_str());
1340 // Use an IOHandler to grab Python code from the user
1341 ScriptAddOptions *options =
1342 new ScriptAddOptions(m_options.m_flags, m_options.m_regex,
1343 m_options.m_name, m_options.m_category);
1345 for (auto &entry : command.entries()) {
1346 if (entry.ref().empty()) {
1347 result.AppendError("empty typenames not allowed");
1351 options->m_target_types << std::string(entry.ref());
1354 m_interpreter.GetPythonCommandsFromIOHandler(
1356 *this, // IOHandlerDelegate
1357 options); // Baton for the "io_handler" that will be passed back into
1358 // our IOHandlerDelegate functions
1359 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1361 return result.Succeeded();
1364 // if I am here, script_format must point to something good, so I can add
1365 // that as a script summary to all interested parties
1369 for (auto &entry : command.entries()) {
1370 CommandObjectTypeSummaryAdd::AddSummary(
1371 ConstString(entry.ref()), script_format,
1372 (m_options.m_regex ? eRegexSummary : eRegularSummary),
1373 m_options.m_category, &error);
1375 result.AppendError(error.AsCString());
1380 if (m_options.m_name) {
1381 AddSummary(m_options.m_name, script_format, eNamedSummary,
1382 m_options.m_category, &error);
1384 result.AppendError(error.AsCString());
1385 result.AppendError("added to types, but not given a name");
1390 return result.Succeeded();
1395 bool CommandObjectTypeSummaryAdd::Execute_StringSummary(
1396 Args &command, CommandReturnObject &result) {
1397 const size_t argc = command.GetArgumentCount();
1399 if (argc < 1 && !m_options.m_name) {
1400 result.AppendErrorWithFormat("%s takes one or more args.\n",
1401 m_cmd_name.c_str());
1405 if (!m_options.m_flags.GetShowMembersOneLiner() &&
1406 m_options.m_format_string.empty()) {
1407 result.AppendError("empty summary strings not allowed");
1411 const char *format_cstr = (m_options.m_flags.GetShowMembersOneLiner()
1413 : m_options.m_format_string.c_str());
1415 // ${var%S} is an endless recursion, prevent it
1416 if (strcmp(format_cstr, "${var%S}") == 0) {
1417 result.AppendError("recursive summary not allowed");
1421 std::unique_ptr<StringSummaryFormat> string_format(
1422 new StringSummaryFormat(m_options.m_flags, format_cstr));
1423 if (!string_format) {
1424 result.AppendError("summary creation failed");
1427 if (string_format->m_error.Fail()) {
1428 result.AppendErrorWithFormat("syntax error: %s",
1429 string_format->m_error.AsCString("<unknown>"));
1432 lldb::TypeSummaryImplSP entry(string_format.release());
1434 // now I have a valid format, let's add it to every type
1436 for (auto &arg_entry : command.entries()) {
1437 if (arg_entry.ref().empty()) {
1438 result.AppendError("empty typenames not allowed");
1441 ConstString typeCS(arg_entry.ref());
1443 AddSummary(typeCS, entry,
1444 (m_options.m_regex ? eRegexSummary : eRegularSummary),
1445 m_options.m_category, &error);
1448 result.AppendError(error.AsCString());
1453 if (m_options.m_name) {
1454 AddSummary(m_options.m_name, entry, eNamedSummary, m_options.m_category,
1457 result.AppendError(error.AsCString());
1458 result.AppendError("added to types, but not given a name");
1463 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1464 return result.Succeeded();
1467 CommandObjectTypeSummaryAdd::CommandObjectTypeSummaryAdd(
1468 CommandInterpreter &interpreter)
1469 : CommandObjectParsed(interpreter, "type summary add",
1470 "Add a new summary style for a type.", nullptr),
1471 IOHandlerDelegateMultiline("DONE"), m_options(interpreter) {
1472 CommandArgumentEntry type_arg;
1473 CommandArgumentData type_style_arg;
1475 type_style_arg.arg_type = eArgTypeName;
1476 type_style_arg.arg_repetition = eArgRepeatPlus;
1478 type_arg.push_back(type_style_arg);
1480 m_arguments.push_back(type_arg);
1484 The following examples of 'type summary add' refer to this code snippet for context:
1490 JustADemo(int p = 1, float v = 0.1) : ptr(new int(p)), value(v) {}
1492 JustADemo demo_instance(42, 3.14);
1494 typedef JustADemo NewDemo;
1495 NewDemo new_demo_instance(42, 3.14);
1497 (lldb) type summary add --summary-string "the answer is ${*var.ptr}" JustADemo
1499 Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42"
1501 (lldb) type summary add --summary-string "the answer is ${*var.ptr}, and the question is ${var.value}" JustADemo
1503 Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42 and the question is 3.14"
1506 "Alternatively, you could define formatting for all pointers to integers and \
1507 rely on that when formatting JustADemo to obtain the same result:"
1510 (lldb) type summary add --summary-string "${var%V} -> ${*var}" "int *"
1511 (lldb) type summary add --summary-string "the answer is ${var.ptr}, and the question is ${var.value}" JustADemo
1514 "Type summaries are automatically applied to derived typedefs, so the examples \
1515 above apply to both JustADemo and NewDemo. The cascade option can be used to \
1516 suppress this behavior:"
1519 (lldb) type summary add --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo -C no
1521 The summary will now be used for values of JustADemo but not NewDemo.
1524 "By default summaries are shown for pointers and references to values of the \
1525 specified type. To suppress formatting for pointers use the -p option, or apply \
1526 the corresponding -r option to suppress formatting for references:"
1529 (lldb) type summary add -p -r --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo
1532 "One-line summaries including all fields in a type can be inferred without supplying an \
1533 explicit summary string by passing the -c option:"
1536 (lldb) type summary add -c JustADemo
1537 (lldb) frame variable demo_instance
1538 (ptr=<address>, value=3.14)
1541 "Type summaries normally suppress the nested display of individual fields. To \
1542 supply a summary to supplement the default structure add the -e option:"
1545 (lldb) type summary add -e --summary-string "*ptr = ${*var.ptr}" JustADemo
1548 "Now when displaying JustADemo values the int* is displayed, followed by the \
1549 standard LLDB sequence of children, one per line:"
1558 "You can also add summaries written in Python. These scripts use lldb public API to \
1559 gather information from your variables and produce a meaningful summary. To start a \
1560 multi-line script use the -P option. The function declaration will be displayed along with \
1561 a comment describing the two arguments. End your script with the word 'DONE' on a line by \
1565 (lldb) type summary add JustADemo -P
1566 def function (valobj,internal_dict):
1567 """valobj: an SBValue which you want to provide a summary for
1568 internal_dict: an LLDB support object not to be used"""
1569 value = valobj.GetChildMemberWithName('value');
1570 return 'My value is ' + value.GetValue();
1573 Alternatively, the -o option can be used when providing a simple one-line Python script:
1575 (lldb) type summary add JustADemo -o "value = valobj.GetChildMemberWithName('value'); return 'My value is ' + value.GetValue();")");
1578 bool CommandObjectTypeSummaryAdd::DoExecute(Args &command,
1579 CommandReturnObject &result) {
1580 WarnOnPotentialUnquotedUnsignedType(command, result);
1582 if (m_options.m_is_add_script) {
1583 #if LLDB_ENABLE_PYTHON
1584 return Execute_ScriptSummary(command, result);
1586 result.AppendError("python is disabled");
1591 return Execute_StringSummary(command, result);
1594 static bool FixArrayTypeNameWithRegex(ConstString &type_name) {
1595 llvm::StringRef type_name_ref(type_name.GetStringRef());
1597 if (type_name_ref.endswith("[]")) {
1598 std::string type_name_str(type_name.GetCString());
1599 type_name_str.resize(type_name_str.length() - 2);
1600 if (type_name_str.back() != ' ')
1601 type_name_str.append(" \\[[0-9]+\\]");
1603 type_name_str.append("\\[[0-9]+\\]");
1604 type_name.SetCString(type_name_str.c_str());
1610 bool CommandObjectTypeSummaryAdd::AddSummary(ConstString type_name,
1611 TypeSummaryImplSP entry,
1612 SummaryFormatType type,
1613 std::string category_name,
1615 lldb::TypeCategoryImplSP category;
1616 DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()),
1619 if (type == eRegularSummary) {
1620 if (FixArrayTypeNameWithRegex(type_name))
1621 type = eRegexSummary;
1624 if (type == eRegexSummary) {
1625 RegularExpression typeRX(type_name.GetStringRef());
1626 if (!typeRX.IsValid()) {
1628 error->SetErrorString(
1629 "regex format error (maybe this is not really a regex?)");
1633 category->GetRegexTypeSummariesContainer()->Delete(type_name);
1634 category->GetRegexTypeSummariesContainer()->Add(std::move(typeRX), entry);
1637 } else if (type == eNamedSummary) {
1638 // system named summaries do not exist (yet?)
1639 DataVisualization::NamedSummaryFormats::Add(type_name, entry);
1642 category->GetTypeSummariesContainer()->Add(std::move(type_name), entry);
1647 // CommandObjectTypeSummaryDelete
1649 class CommandObjectTypeSummaryDelete : public CommandObjectTypeFormatterDelete {
1651 CommandObjectTypeSummaryDelete(CommandInterpreter &interpreter)
1652 : CommandObjectTypeFormatterDelete(
1654 eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary,
1655 "type summary delete", "Delete an existing summary for a type.") {}
1657 ~CommandObjectTypeSummaryDelete() override = default;
1660 bool FormatterSpecificDeletion(ConstString typeCS) override {
1661 if (m_options.m_language != lldb::eLanguageTypeUnknown)
1663 return DataVisualization::NamedSummaryFormats::Delete(typeCS);
1667 class CommandObjectTypeSummaryClear : public CommandObjectTypeFormatterClear {
1669 CommandObjectTypeSummaryClear(CommandInterpreter &interpreter)
1670 : CommandObjectTypeFormatterClear(
1672 eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary,
1673 "type summary clear", "Delete all existing summaries.") {}
1676 void FormatterSpecificDeletion() override {
1677 DataVisualization::NamedSummaryFormats::Clear();
1681 // CommandObjectTypeSummaryList
1683 class CommandObjectTypeSummaryList
1684 : public CommandObjectTypeFormatterList<TypeSummaryImpl> {
1686 CommandObjectTypeSummaryList(CommandInterpreter &interpreter)
1687 : CommandObjectTypeFormatterList(interpreter, "type summary list",
1688 "Show a list of current summaries.") {}
1691 bool FormatterSpecificList(CommandReturnObject &result) override {
1692 if (DataVisualization::NamedSummaryFormats::GetCount() > 0) {
1693 result.GetOutputStream().Printf("Named summaries:\n");
1694 DataVisualization::NamedSummaryFormats::ForEach(
1695 [&result](const TypeMatcher &type_matcher,
1696 const TypeSummaryImplSP &summary_sp) -> bool {
1697 result.GetOutputStream().Printf(
1698 "%s: %s\n", type_matcher.GetMatchString().GetCString(),
1699 summary_sp->GetDescription().c_str());
1708 // CommandObjectTypeCategoryDefine
1709 #define LLDB_OPTIONS_type_category_define
1710 #include "CommandOptions.inc"
1712 class CommandObjectTypeCategoryDefine : public CommandObjectParsed {
1713 class CommandOptions : public Options {
1716 : Options(), m_define_enabled(false, false),
1717 m_cate_language(eLanguageTypeUnknown, eLanguageTypeUnknown) {}
1719 ~CommandOptions() override = default;
1721 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1722 ExecutionContext *execution_context) override {
1724 const int short_option = m_getopt_table[option_idx].val;
1726 switch (short_option) {
1728 m_define_enabled.SetValueFromString(llvm::StringRef("true"));
1731 error = m_cate_language.SetValueFromString(option_arg);
1734 llvm_unreachable("Unimplemented option");
1740 void OptionParsingStarting(ExecutionContext *execution_context) override {
1741 m_define_enabled.Clear();
1742 m_cate_language.Clear();
1745 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1746 return llvm::makeArrayRef(g_type_category_define_options);
1749 // Instance variables to hold the values for command options.
1751 OptionValueBoolean m_define_enabled;
1752 OptionValueLanguage m_cate_language;
1755 CommandOptions m_options;
1757 Options *GetOptions() override { return &m_options; }
1760 CommandObjectTypeCategoryDefine(CommandInterpreter &interpreter)
1761 : CommandObjectParsed(interpreter, "type category define",
1762 "Define a new category as a source of formatters.",
1765 CommandArgumentEntry type_arg;
1766 CommandArgumentData type_style_arg;
1768 type_style_arg.arg_type = eArgTypeName;
1769 type_style_arg.arg_repetition = eArgRepeatPlus;
1771 type_arg.push_back(type_style_arg);
1773 m_arguments.push_back(type_arg);
1776 ~CommandObjectTypeCategoryDefine() override = default;
1779 HandleArgumentCompletion(CompletionRequest &request,
1780 OptionElementVector &opt_element_vector) override {
1781 CommandCompletions::InvokeCommonCompletionCallbacks(
1782 GetCommandInterpreter(),
1783 CommandCompletions::eTypeCategoryNameCompletion, request, nullptr);
1787 bool DoExecute(Args &command, CommandReturnObject &result) override {
1788 const size_t argc = command.GetArgumentCount();
1791 result.AppendErrorWithFormat("%s takes 1 or more args.\n",
1792 m_cmd_name.c_str());
1796 for (auto &entry : command.entries()) {
1797 TypeCategoryImplSP category_sp;
1798 if (DataVisualization::Categories::GetCategory(ConstString(entry.ref()),
1801 category_sp->AddLanguage(m_options.m_cate_language.GetCurrentValue());
1802 if (m_options.m_define_enabled.GetCurrentValue())
1803 DataVisualization::Categories::Enable(category_sp,
1804 TypeCategoryMap::Default);
1808 result.SetStatus(eReturnStatusSuccessFinishResult);
1809 return result.Succeeded();
1813 // CommandObjectTypeCategoryEnable
1814 #define LLDB_OPTIONS_type_category_enable
1815 #include "CommandOptions.inc"
1817 class CommandObjectTypeCategoryEnable : public CommandObjectParsed {
1818 class CommandOptions : public Options {
1820 CommandOptions() : Options() {}
1822 ~CommandOptions() override = default;
1824 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1825 ExecutionContext *execution_context) override {
1827 const int short_option = m_getopt_table[option_idx].val;
1829 switch (short_option) {
1831 if (!option_arg.empty()) {
1832 m_language = Language::GetLanguageTypeFromString(option_arg);
1833 if (m_language == lldb::eLanguageTypeUnknown)
1834 error.SetErrorStringWithFormat("unrecognized language '%s'",
1835 option_arg.str().c_str());
1839 llvm_unreachable("Unimplemented option");
1845 void OptionParsingStarting(ExecutionContext *execution_context) override {
1846 m_language = lldb::eLanguageTypeUnknown;
1849 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1850 return llvm::makeArrayRef(g_type_category_enable_options);
1853 // Instance variables to hold the values for command options.
1855 lldb::LanguageType m_language;
1858 CommandOptions m_options;
1860 Options *GetOptions() override { return &m_options; }
1863 CommandObjectTypeCategoryEnable(CommandInterpreter &interpreter)
1864 : CommandObjectParsed(interpreter, "type category enable",
1865 "Enable a category as a source of formatters.",
1868 CommandArgumentEntry type_arg;
1869 CommandArgumentData type_style_arg;
1871 type_style_arg.arg_type = eArgTypeName;
1872 type_style_arg.arg_repetition = eArgRepeatPlus;
1874 type_arg.push_back(type_style_arg);
1876 m_arguments.push_back(type_arg);
1879 ~CommandObjectTypeCategoryEnable() override = default;
1882 HandleArgumentCompletion(CompletionRequest &request,
1883 OptionElementVector &opt_element_vector) override {
1884 CommandCompletions::InvokeCommonCompletionCallbacks(
1885 GetCommandInterpreter(),
1886 CommandCompletions::eTypeCategoryNameCompletion, request, nullptr);
1890 bool DoExecute(Args &command, CommandReturnObject &result) override {
1891 const size_t argc = command.GetArgumentCount();
1893 if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) {
1894 result.AppendErrorWithFormat("%s takes arguments and/or a language",
1895 m_cmd_name.c_str());
1899 if (argc == 1 && strcmp(command.GetArgumentAtIndex(0), "*") == 0) {
1900 DataVisualization::Categories::EnableStar();
1901 } else if (argc > 0) {
1902 for (int i = argc - 1; i >= 0; i--) {
1903 const char *typeA = command.GetArgumentAtIndex(i);
1904 ConstString typeCS(typeA);
1907 result.AppendError("empty category name not allowed");
1910 DataVisualization::Categories::Enable(typeCS);
1911 lldb::TypeCategoryImplSP cate;
1912 if (DataVisualization::Categories::GetCategory(typeCS, cate) && cate) {
1913 if (cate->GetCount() == 0) {
1914 result.AppendWarning("empty category enabled (typo?)");
1920 if (m_options.m_language != lldb::eLanguageTypeUnknown)
1921 DataVisualization::Categories::Enable(m_options.m_language);
1923 result.SetStatus(eReturnStatusSuccessFinishResult);
1924 return result.Succeeded();
1928 // CommandObjectTypeCategoryDelete
1930 class CommandObjectTypeCategoryDelete : public CommandObjectParsed {
1932 CommandObjectTypeCategoryDelete(CommandInterpreter &interpreter)
1933 : CommandObjectParsed(interpreter, "type category delete",
1934 "Delete a category and all associated formatters.",
1936 CommandArgumentEntry type_arg;
1937 CommandArgumentData type_style_arg;
1939 type_style_arg.arg_type = eArgTypeName;
1940 type_style_arg.arg_repetition = eArgRepeatPlus;
1942 type_arg.push_back(type_style_arg);
1944 m_arguments.push_back(type_arg);
1947 ~CommandObjectTypeCategoryDelete() override = default;
1950 HandleArgumentCompletion(CompletionRequest &request,
1951 OptionElementVector &opt_element_vector) override {
1952 CommandCompletions::InvokeCommonCompletionCallbacks(
1953 GetCommandInterpreter(),
1954 CommandCompletions::eTypeCategoryNameCompletion, request, nullptr);
1958 bool DoExecute(Args &command, CommandReturnObject &result) override {
1959 const size_t argc = command.GetArgumentCount();
1962 result.AppendErrorWithFormat("%s takes 1 or more arg.\n",
1963 m_cmd_name.c_str());
1967 bool success = true;
1969 // the order is not relevant here
1970 for (int i = argc - 1; i >= 0; i--) {
1971 const char *typeA = command.GetArgumentAtIndex(i);
1972 ConstString typeCS(typeA);
1975 result.AppendError("empty category name not allowed");
1978 if (!DataVisualization::Categories::Delete(typeCS))
1979 success = false; // keep deleting even if we hit an error
1982 result.SetStatus(eReturnStatusSuccessFinishResult);
1983 return result.Succeeded();
1985 result.AppendError("cannot delete one or more categories\n");
1991 // CommandObjectTypeCategoryDisable
1992 #define LLDB_OPTIONS_type_category_disable
1993 #include "CommandOptions.inc"
1995 class CommandObjectTypeCategoryDisable : public CommandObjectParsed {
1996 class CommandOptions : public Options {
1998 CommandOptions() : Options() {}
2000 ~CommandOptions() override = default;
2002 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2003 ExecutionContext *execution_context) override {
2005 const int short_option = m_getopt_table[option_idx].val;
2007 switch (short_option) {
2009 if (!option_arg.empty()) {
2010 m_language = Language::GetLanguageTypeFromString(option_arg);
2011 if (m_language == lldb::eLanguageTypeUnknown)
2012 error.SetErrorStringWithFormat("unrecognized language '%s'",
2013 option_arg.str().c_str());
2017 llvm_unreachable("Unimplemented option");
2023 void OptionParsingStarting(ExecutionContext *execution_context) override {
2024 m_language = lldb::eLanguageTypeUnknown;
2027 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2028 return llvm::makeArrayRef(g_type_category_disable_options);
2031 // Instance variables to hold the values for command options.
2033 lldb::LanguageType m_language;
2036 CommandOptions m_options;
2038 Options *GetOptions() override { return &m_options; }
2041 CommandObjectTypeCategoryDisable(CommandInterpreter &interpreter)
2042 : CommandObjectParsed(interpreter, "type category disable",
2043 "Disable a category as a source of formatters.",
2046 CommandArgumentEntry type_arg;
2047 CommandArgumentData type_style_arg;
2049 type_style_arg.arg_type = eArgTypeName;
2050 type_style_arg.arg_repetition = eArgRepeatPlus;
2052 type_arg.push_back(type_style_arg);
2054 m_arguments.push_back(type_arg);
2057 ~CommandObjectTypeCategoryDisable() override = default;
2060 HandleArgumentCompletion(CompletionRequest &request,
2061 OptionElementVector &opt_element_vector) override {
2062 CommandCompletions::InvokeCommonCompletionCallbacks(
2063 GetCommandInterpreter(),
2064 CommandCompletions::eTypeCategoryNameCompletion, request, nullptr);
2068 bool DoExecute(Args &command, CommandReturnObject &result) override {
2069 const size_t argc = command.GetArgumentCount();
2071 if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) {
2072 result.AppendErrorWithFormat("%s takes arguments and/or a language",
2073 m_cmd_name.c_str());
2077 if (argc == 1 && strcmp(command.GetArgumentAtIndex(0), "*") == 0) {
2078 DataVisualization::Categories::DisableStar();
2079 } else if (argc > 0) {
2080 // the order is not relevant here
2081 for (int i = argc - 1; i >= 0; i--) {
2082 const char *typeA = command.GetArgumentAtIndex(i);
2083 ConstString typeCS(typeA);
2086 result.AppendError("empty category name not allowed");
2089 DataVisualization::Categories::Disable(typeCS);
2093 if (m_options.m_language != lldb::eLanguageTypeUnknown)
2094 DataVisualization::Categories::Disable(m_options.m_language);
2096 result.SetStatus(eReturnStatusSuccessFinishResult);
2097 return result.Succeeded();
2101 // CommandObjectTypeCategoryList
2103 class CommandObjectTypeCategoryList : public CommandObjectParsed {
2105 CommandObjectTypeCategoryList(CommandInterpreter &interpreter)
2106 : CommandObjectParsed(interpreter, "type category list",
2107 "Provide a list of all existing categories.",
2109 CommandArgumentEntry type_arg;
2110 CommandArgumentData type_style_arg;
2112 type_style_arg.arg_type = eArgTypeName;
2113 type_style_arg.arg_repetition = eArgRepeatOptional;
2115 type_arg.push_back(type_style_arg);
2117 m_arguments.push_back(type_arg);
2120 ~CommandObjectTypeCategoryList() override = default;
2123 HandleArgumentCompletion(CompletionRequest &request,
2124 OptionElementVector &opt_element_vector) override {
2125 if (request.GetCursorIndex())
2127 CommandCompletions::InvokeCommonCompletionCallbacks(
2128 GetCommandInterpreter(),
2129 CommandCompletions::eTypeCategoryNameCompletion, request, nullptr);
2133 bool DoExecute(Args &command, CommandReturnObject &result) override {
2134 const size_t argc = command.GetArgumentCount();
2136 std::unique_ptr<RegularExpression> regex;
2139 const char *arg = command.GetArgumentAtIndex(0);
2140 regex = std::make_unique<RegularExpression>(arg);
2141 if (!regex->IsValid()) {
2142 result.AppendErrorWithFormat(
2143 "syntax error in category regular expression '%s'", arg);
2146 } else if (argc != 0) {
2147 result.AppendErrorWithFormat("%s takes 0 or one arg.\n",
2148 m_cmd_name.c_str());
2152 DataVisualization::Categories::ForEach(
2153 [®ex, &result](const lldb::TypeCategoryImplSP &category_sp) -> bool {
2156 if (regex->GetText() == category_sp->GetName()) {
2158 } else if (regex->Execute(category_sp->GetName())) {
2166 result.GetOutputStream().Printf(
2167 "Category: %s\n", category_sp->GetDescription().c_str());
2172 result.SetStatus(eReturnStatusSuccessFinishResult);
2173 return result.Succeeded();
2177 // CommandObjectTypeFilterList
2179 class CommandObjectTypeFilterList
2180 : public CommandObjectTypeFormatterList<TypeFilterImpl> {
2182 CommandObjectTypeFilterList(CommandInterpreter &interpreter)
2183 : CommandObjectTypeFormatterList(interpreter, "type filter list",
2184 "Show a list of current filters.") {}
2187 #if LLDB_ENABLE_PYTHON
2189 // CommandObjectTypeSynthList
2191 class CommandObjectTypeSynthList
2192 : public CommandObjectTypeFormatterList<SyntheticChildren> {
2194 CommandObjectTypeSynthList(CommandInterpreter &interpreter)
2195 : CommandObjectTypeFormatterList(
2196 interpreter, "type synthetic list",
2197 "Show a list of current synthetic providers.") {}
2202 // CommandObjectTypeFilterDelete
2204 class CommandObjectTypeFilterDelete : public CommandObjectTypeFormatterDelete {
2206 CommandObjectTypeFilterDelete(CommandInterpreter &interpreter)
2207 : CommandObjectTypeFormatterDelete(
2209 eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter,
2210 "type filter delete", "Delete an existing filter for a type.") {}
2212 ~CommandObjectTypeFilterDelete() override = default;
2215 #if LLDB_ENABLE_PYTHON
2217 // CommandObjectTypeSynthDelete
2219 class CommandObjectTypeSynthDelete : public CommandObjectTypeFormatterDelete {
2221 CommandObjectTypeSynthDelete(CommandInterpreter &interpreter)
2222 : CommandObjectTypeFormatterDelete(
2224 eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth,
2225 "type synthetic delete",
2226 "Delete an existing synthetic provider for a type.") {}
2228 ~CommandObjectTypeSynthDelete() override = default;
2233 // CommandObjectTypeFilterClear
2235 class CommandObjectTypeFilterClear : public CommandObjectTypeFormatterClear {
2237 CommandObjectTypeFilterClear(CommandInterpreter &interpreter)
2238 : CommandObjectTypeFormatterClear(
2240 eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter,
2241 "type filter clear", "Delete all existing filter.") {}
2244 #if LLDB_ENABLE_PYTHON
2245 // CommandObjectTypeSynthClear
2247 class CommandObjectTypeSynthClear : public CommandObjectTypeFormatterClear {
2249 CommandObjectTypeSynthClear(CommandInterpreter &interpreter)
2250 : CommandObjectTypeFormatterClear(
2252 eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth,
2253 "type synthetic clear",
2254 "Delete all existing synthetic providers.") {}
2257 bool CommandObjectTypeSynthAdd::Execute_HandwritePython(
2258 Args &command, CommandReturnObject &result) {
2259 SynthAddOptions *options = new SynthAddOptions(
2260 m_options.m_skip_pointers, m_options.m_skip_references,
2261 m_options.m_cascade, m_options.m_regex, m_options.m_category);
2263 for (auto &entry : command.entries()) {
2264 if (entry.ref().empty()) {
2265 result.AppendError("empty typenames not allowed");
2269 options->m_target_types << std::string(entry.ref());
2272 m_interpreter.GetPythonCommandsFromIOHandler(
2274 *this, // IOHandlerDelegate
2275 options); // Baton for the "io_handler" that will be passed back into our
2276 // IOHandlerDelegate functions
2277 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2278 return result.Succeeded();
2281 bool CommandObjectTypeSynthAdd::Execute_PythonClass(
2282 Args &command, CommandReturnObject &result) {
2283 const size_t argc = command.GetArgumentCount();
2286 result.AppendErrorWithFormat("%s takes one or more args.\n",
2287 m_cmd_name.c_str());
2291 if (m_options.m_class_name.empty() && !m_options.m_input_python) {
2292 result.AppendErrorWithFormat("%s needs either a Python class name or -P to "
2293 "directly input Python code.\n",
2294 m_cmd_name.c_str());
2298 SyntheticChildrenSP entry;
2300 ScriptedSyntheticChildren *impl = new ScriptedSyntheticChildren(
2301 SyntheticChildren::Flags()
2302 .SetCascades(m_options.m_cascade)
2303 .SetSkipPointers(m_options.m_skip_pointers)
2304 .SetSkipReferences(m_options.m_skip_references),
2305 m_options.m_class_name.c_str());
2309 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
2312 !interpreter->CheckObjectExists(impl->GetPythonClassName()))
2313 result.AppendWarning("The provided class does not exist - please define it "
2314 "before attempting to use this synthetic provider");
2316 // now I have a valid provider, let's add it to every type
2318 lldb::TypeCategoryImplSP category;
2319 DataVisualization::Categories::GetCategory(
2320 ConstString(m_options.m_category.c_str()), category);
2324 for (auto &arg_entry : command.entries()) {
2325 if (arg_entry.ref().empty()) {
2326 result.AppendError("empty typenames not allowed");
2330 ConstString typeCS(arg_entry.ref());
2331 if (!AddSynth(typeCS, entry,
2332 m_options.m_regex ? eRegexSynth : eRegularSynth,
2333 m_options.m_category, &error)) {
2334 result.AppendError(error.AsCString());
2339 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2340 return result.Succeeded();
2343 CommandObjectTypeSynthAdd::CommandObjectTypeSynthAdd(
2344 CommandInterpreter &interpreter)
2345 : CommandObjectParsed(interpreter, "type synthetic add",
2346 "Add a new synthetic provider for a type.", nullptr),
2347 IOHandlerDelegateMultiline("DONE"), m_options() {
2348 CommandArgumentEntry type_arg;
2349 CommandArgumentData type_style_arg;
2351 type_style_arg.arg_type = eArgTypeName;
2352 type_style_arg.arg_repetition = eArgRepeatPlus;
2354 type_arg.push_back(type_style_arg);
2356 m_arguments.push_back(type_arg);
2359 bool CommandObjectTypeSynthAdd::AddSynth(ConstString type_name,
2360 SyntheticChildrenSP entry,
2361 SynthFormatType type,
2362 std::string category_name,
2364 lldb::TypeCategoryImplSP category;
2365 DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()),
2368 if (type == eRegularSynth) {
2369 if (FixArrayTypeNameWithRegex(type_name))
2373 if (category->AnyMatches(
2374 type_name, eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter,
2377 error->SetErrorStringWithFormat("cannot add synthetic for type %s when "
2378 "filter is defined in same category!",
2379 type_name.AsCString());
2383 if (type == eRegexSynth) {
2384 RegularExpression typeRX(type_name.GetStringRef());
2385 if (!typeRX.IsValid()) {
2387 error->SetErrorString(
2388 "regex format error (maybe this is not really a regex?)");
2392 category->GetRegexTypeSyntheticsContainer()->Delete(type_name);
2393 category->GetRegexTypeSyntheticsContainer()->Add(std::move(typeRX), entry);
2397 category->GetTypeSyntheticsContainer()->Add(std::move(type_name), entry);
2403 #define LLDB_OPTIONS_type_filter_add
2404 #include "CommandOptions.inc"
2406 class CommandObjectTypeFilterAdd : public CommandObjectParsed {
2408 class CommandOptions : public Options {
2409 typedef std::vector<std::string> option_vector;
2412 CommandOptions() : Options() {}
2414 ~CommandOptions() override = default;
2416 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2417 ExecutionContext *execution_context) override {
2419 const int short_option = m_getopt_table[option_idx].val;
2422 switch (short_option) {
2424 m_cascade = OptionArgParser::ToBoolean(option_arg, true, &success);
2426 error.SetErrorStringWithFormat("invalid value for cascade: %s",
2427 option_arg.str().c_str());
2430 m_expr_paths.push_back(std::string(option_arg));
2431 has_child_list = true;
2434 m_skip_pointers = true;
2437 m_skip_references = true;
2440 m_category = std::string(option_arg);
2446 llvm_unreachable("Unimplemented option");
2452 void OptionParsingStarting(ExecutionContext *execution_context) override {
2454 m_skip_pointers = false;
2455 m_skip_references = false;
2456 m_category = "default";
2457 m_expr_paths.clear();
2458 has_child_list = false;
2462 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2463 return llvm::makeArrayRef(g_type_filter_add_options);
2466 // Instance variables to hold the values for command options.
2469 bool m_skip_references;
2470 bool m_skip_pointers;
2471 bool m_input_python;
2472 option_vector m_expr_paths;
2473 std::string m_category;
2474 bool has_child_list;
2477 typedef option_vector::iterator ExpressionPathsIterator;
2480 CommandOptions m_options;
2482 Options *GetOptions() override { return &m_options; }
2484 enum FilterFormatType { eRegularFilter, eRegexFilter };
2486 bool AddFilter(ConstString type_name, TypeFilterImplSP entry,
2487 FilterFormatType type, std::string category_name,
2489 lldb::TypeCategoryImplSP category;
2490 DataVisualization::Categories::GetCategory(
2491 ConstString(category_name.c_str()), category);
2493 if (type == eRegularFilter) {
2494 if (FixArrayTypeNameWithRegex(type_name))
2495 type = eRegexFilter;
2498 if (category->AnyMatches(
2499 type_name, eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth,
2502 error->SetErrorStringWithFormat("cannot add filter for type %s when "
2503 "synthetic is defined in same "
2505 type_name.AsCString());
2509 if (type == eRegexFilter) {
2510 RegularExpression typeRX(type_name.GetStringRef());
2511 if (!typeRX.IsValid()) {
2513 error->SetErrorString(
2514 "regex format error (maybe this is not really a regex?)");
2518 category->GetRegexTypeFiltersContainer()->Delete(type_name);
2519 category->GetRegexTypeFiltersContainer()->Add(std::move(typeRX), entry);
2523 category->GetTypeFiltersContainer()->Add(std::move(type_name), entry);
2529 CommandObjectTypeFilterAdd(CommandInterpreter &interpreter)
2530 : CommandObjectParsed(interpreter, "type filter add",
2531 "Add a new filter for a type.", nullptr),
2533 CommandArgumentEntry type_arg;
2534 CommandArgumentData type_style_arg;
2536 type_style_arg.arg_type = eArgTypeName;
2537 type_style_arg.arg_repetition = eArgRepeatPlus;
2539 type_arg.push_back(type_style_arg);
2541 m_arguments.push_back(type_arg);
2545 The following examples of 'type filter add' refer to this code snippet for context:
2560 Adding a simple filter:
2562 (lldb) type filter add --child a --child g Foo
2563 (lldb) frame variable my_foo
2566 "Produces output where only a and g are displayed. Other children of my_foo \
2567 (b, c, d, e, f, h and i) are available by asking for them explicitly:"
2570 (lldb) frame variable my_foo.b my_foo.c my_foo.i
2573 "The formatting option --raw on frame variable bypasses the filter, showing \
2574 all children of my_foo as if no filter was defined:"
2577 (lldb) frame variable my_foo --raw)");
2580 ~CommandObjectTypeFilterAdd() override = default;
2583 bool DoExecute(Args &command, CommandReturnObject &result) override {
2584 const size_t argc = command.GetArgumentCount();
2587 result.AppendErrorWithFormat("%s takes one or more args.\n",
2588 m_cmd_name.c_str());
2592 if (m_options.m_expr_paths.empty()) {
2593 result.AppendErrorWithFormat("%s needs one or more children.\n",
2594 m_cmd_name.c_str());
2598 TypeFilterImplSP entry(new TypeFilterImpl(
2599 SyntheticChildren::Flags()
2600 .SetCascades(m_options.m_cascade)
2601 .SetSkipPointers(m_options.m_skip_pointers)
2602 .SetSkipReferences(m_options.m_skip_references)));
2604 // go through the expression paths
2605 CommandOptions::ExpressionPathsIterator begin,
2606 end = m_options.m_expr_paths.end();
2608 for (begin = m_options.m_expr_paths.begin(); begin != end; begin++)
2609 entry->AddExpressionPath(*begin);
2611 // now I have a valid provider, let's add it to every type
2613 lldb::TypeCategoryImplSP category;
2614 DataVisualization::Categories::GetCategory(
2615 ConstString(m_options.m_category.c_str()), category);
2619 WarnOnPotentialUnquotedUnsignedType(command, result);
2621 for (auto &arg_entry : command.entries()) {
2622 if (arg_entry.ref().empty()) {
2623 result.AppendError("empty typenames not allowed");
2627 ConstString typeCS(arg_entry.ref());
2628 if (!AddFilter(typeCS, entry,
2629 m_options.m_regex ? eRegexFilter : eRegularFilter,
2630 m_options.m_category, &error)) {
2631 result.AppendError(error.AsCString());
2636 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2637 return result.Succeeded();
2642 #define LLDB_OPTIONS_type_lookup
2643 #include "CommandOptions.inc"
2645 class CommandObjectTypeLookup : public CommandObjectRaw {
2647 // this function is allowed to do a more aggressive job at guessing languages
2648 // than the expression parser is comfortable with - so leave the original
2649 // call alone and add one that is specific to type lookup
2650 lldb::LanguageType GuessLanguage(StackFrame *frame) {
2651 lldb::LanguageType lang_type = lldb::eLanguageTypeUnknown;
2656 lang_type = frame->GuessLanguage();
2657 if (lang_type != lldb::eLanguageTypeUnknown)
2660 Symbol *s = frame->GetSymbolContext(eSymbolContextSymbol).symbol;
2662 lang_type = s->GetMangled().GuessLanguage();
2667 class CommandOptions : public OptionGroup {
2669 CommandOptions() : OptionGroup() {}
2671 ~CommandOptions() override = default;
2673 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2674 return llvm::makeArrayRef(g_type_lookup_options);
2677 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
2678 ExecutionContext *execution_context) override {
2681 const int short_option = g_type_lookup_options[option_idx].short_option;
2683 switch (short_option) {
2689 m_language = Language::GetLanguageTypeFromString(option_value);
2693 llvm_unreachable("Unimplemented option");
2699 void OptionParsingStarting(ExecutionContext *execution_context) override {
2700 m_show_help = false;
2701 m_language = eLanguageTypeUnknown;
2704 // Options table: Required for subclasses of Options.
2706 bool m_show_help = false;
2707 lldb::LanguageType m_language = eLanguageTypeUnknown;
2710 OptionGroupOptions m_option_group;
2711 CommandOptions m_command_options;
2714 CommandObjectTypeLookup(CommandInterpreter &interpreter)
2715 : CommandObjectRaw(interpreter, "type lookup",
2716 "Lookup types and declarations in the current target, "
2717 "following language-specific naming conventions.",
2718 "type lookup <type-specifier>",
2719 eCommandRequiresTarget),
2720 m_option_group(), m_command_options() {
2721 m_option_group.Append(&m_command_options);
2722 m_option_group.Finalize();
2725 ~CommandObjectTypeLookup() override = default;
2727 Options *GetOptions() override { return &m_option_group; }
2729 llvm::StringRef GetHelpLong() override {
2730 if (!m_cmd_help_long.empty())
2731 return m_cmd_help_long;
2733 StreamString stream;
2734 Language::ForEach([&](Language *lang) {
2735 if (const char *help = lang->GetLanguageSpecificTypeLookupHelp())
2736 stream.Printf("%s\n", help);
2740 m_cmd_help_long = std::string(stream.GetString());
2741 return m_cmd_help_long;
2744 bool DoExecute(llvm::StringRef raw_command_line,
2745 CommandReturnObject &result) override {
2746 if (raw_command_line.empty()) {
2748 "type lookup cannot be invoked without a type name as argument");
2752 auto exe_ctx = GetCommandInterpreter().GetExecutionContext();
2753 m_option_group.NotifyOptionParsingStarting(&exe_ctx);
2755 OptionsWithRaw args(raw_command_line);
2756 const char *name_of_type = args.GetRawPart().c_str();
2759 if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group,
2763 ExecutionContextScope *best_scope = exe_ctx.GetBestExecutionContextScope();
2765 bool any_found = false;
2767 std::vector<Language *> languages;
2769 bool is_global_search = false;
2770 LanguageType guessed_language = lldb::eLanguageTypeUnknown;
2772 if ((is_global_search =
2773 (m_command_options.m_language == eLanguageTypeUnknown))) {
2774 Language::ForEach([&](Language *lang) {
2775 languages.push_back(lang);
2779 languages.push_back(Language::FindPlugin(m_command_options.m_language));
2782 // This is not the most efficient way to do this, but we support very few
2783 // languages so the cost of the sort is going to be dwarfed by the actual
2785 if (StackFrame *frame = m_exe_ctx.GetFramePtr()) {
2786 guessed_language = GuessLanguage(frame);
2787 if (guessed_language != eLanguageTypeUnknown) {
2789 languages.begin(), languages.end(),
2790 [guessed_language](Language *lang1, Language *lang2) -> bool {
2791 if (!lang1 || !lang2)
2793 LanguageType lt1 = lang1->GetLanguageType();
2794 LanguageType lt2 = lang2->GetLanguageType();
2795 if (lt1 == guessed_language)
2796 return true; // make the selected frame's language come first
2797 if (lt2 == guessed_language)
2798 return false; // make the selected frame's language come first
2799 return (lt1 < lt2); // normal comparison otherwise
2804 bool is_first_language = true;
2806 for (Language *language : languages) {
2810 if (auto scavenger = language->GetTypeScavenger()) {
2811 Language::TypeScavenger::ResultSet search_results;
2812 if (scavenger->Find(best_scope, name_of_type, search_results) > 0) {
2813 for (const auto &search_result : search_results) {
2814 if (search_result && search_result->IsValid()) {
2816 search_result->DumpToStream(result.GetOutputStream(),
2817 this->m_command_options.m_show_help);
2822 // this is "type lookup SomeName" and we did find a match, so get out
2823 if (any_found && is_global_search)
2825 else if (is_first_language && is_global_search &&
2826 guessed_language != lldb::eLanguageTypeUnknown) {
2827 is_first_language = false;
2828 result.GetOutputStream().Printf(
2829 "no type was found in the current language %s matching '%s'; "
2830 "performing a global search across all languages\n",
2831 Language::GetNameForLanguageType(guessed_language), name_of_type);
2836 result.AppendMessageWithFormat("no type was found matching '%s'\n",
2839 result.SetStatus(any_found ? lldb::eReturnStatusSuccessFinishResult
2840 : lldb::eReturnStatusSuccessFinishNoResult);
2845 template <typename FormatterType>
2846 class CommandObjectFormatterInfo : public CommandObjectRaw {
2848 typedef std::function<typename FormatterType::SharedPointer(ValueObject &)>
2850 CommandObjectFormatterInfo(CommandInterpreter &interpreter,
2851 const char *formatter_name,
2852 DiscoveryFunction discovery_func)
2853 : CommandObjectRaw(interpreter, "", "", "", eCommandRequiresFrame),
2854 m_formatter_name(formatter_name ? formatter_name : ""),
2855 m_discovery_function(discovery_func) {
2857 name.Printf("type %s info", formatter_name);
2858 SetCommandName(name.GetString());
2860 help.Printf("This command evaluates the provided expression and shows "
2861 "which %s is applied to the resulting value (if any).",
2863 SetHelp(help.GetString());
2864 StreamString syntax;
2865 syntax.Printf("type %s info <expr>", formatter_name);
2866 SetSyntax(syntax.GetString());
2869 ~CommandObjectFormatterInfo() override = default;
2872 bool DoExecute(llvm::StringRef command,
2873 CommandReturnObject &result) override {
2874 TargetSP target_sp = GetDebugger().GetSelectedTarget();
2875 Thread *thread = GetDefaultThread();
2877 result.AppendError("no default thread");
2881 StackFrameSP frame_sp = thread->GetSelectedFrame();
2882 ValueObjectSP result_valobj_sp;
2883 EvaluateExpressionOptions options;
2884 lldb::ExpressionResults expr_result = target_sp->EvaluateExpression(
2885 command, frame_sp.get(), result_valobj_sp, options);
2886 if (expr_result == eExpressionCompleted && result_valobj_sp) {
2888 result_valobj_sp->GetQualifiedRepresentationIfAvailable(
2889 target_sp->GetPreferDynamicValue(),
2890 target_sp->GetEnableSyntheticValue());
2891 typename FormatterType::SharedPointer formatter_sp =
2892 m_discovery_function(*result_valobj_sp);
2894 std::string description(formatter_sp->GetDescription());
2895 result.GetOutputStream()
2896 << m_formatter_name << " applied to ("
2897 << result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>")
2898 << ") " << command << " is: " << description << "\n";
2899 result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
2901 result.GetOutputStream()
2902 << "no " << m_formatter_name << " applies to ("
2903 << result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>")
2904 << ") " << command << "\n";
2905 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
2909 result.AppendError("failed to evaluate expression");
2915 std::string m_formatter_name;
2916 DiscoveryFunction m_discovery_function;
2919 class CommandObjectTypeFormat : public CommandObjectMultiword {
2921 CommandObjectTypeFormat(CommandInterpreter &interpreter)
2922 : CommandObjectMultiword(
2923 interpreter, "type format",
2924 "Commands for customizing value display formats.",
2925 "type format [<sub-command-options>] ") {
2927 "add", CommandObjectSP(new CommandObjectTypeFormatAdd(interpreter)));
2928 LoadSubCommand("clear", CommandObjectSP(
2929 new CommandObjectTypeFormatClear(interpreter)));
2930 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFormatDelete(
2933 "list", CommandObjectSP(new CommandObjectTypeFormatList(interpreter)));
2935 "info", CommandObjectSP(new CommandObjectFormatterInfo<TypeFormatImpl>(
2936 interpreter, "format",
2937 [](ValueObject &valobj) -> TypeFormatImpl::SharedPointer {
2938 return valobj.GetValueFormat();
2942 ~CommandObjectTypeFormat() override = default;
2945 #if LLDB_ENABLE_PYTHON
2947 class CommandObjectTypeSynth : public CommandObjectMultiword {
2949 CommandObjectTypeSynth(CommandInterpreter &interpreter)
2950 : CommandObjectMultiword(
2951 interpreter, "type synthetic",
2952 "Commands for operating on synthetic type representations.",
2953 "type synthetic [<sub-command-options>] ") {
2954 LoadSubCommand("add",
2955 CommandObjectSP(new CommandObjectTypeSynthAdd(interpreter)));
2957 "clear", CommandObjectSP(new CommandObjectTypeSynthClear(interpreter)));
2958 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSynthDelete(
2961 "list", CommandObjectSP(new CommandObjectTypeSynthList(interpreter)));
2964 CommandObjectSP(new CommandObjectFormatterInfo<SyntheticChildren>(
2965 interpreter, "synthetic",
2966 [](ValueObject &valobj) -> SyntheticChildren::SharedPointer {
2967 return valobj.GetSyntheticChildren();
2971 ~CommandObjectTypeSynth() override = default;
2976 class CommandObjectTypeFilter : public CommandObjectMultiword {
2978 CommandObjectTypeFilter(CommandInterpreter &interpreter)
2979 : CommandObjectMultiword(interpreter, "type filter",
2980 "Commands for operating on type filters.",
2981 "type synthetic [<sub-command-options>] ") {
2983 "add", CommandObjectSP(new CommandObjectTypeFilterAdd(interpreter)));
2984 LoadSubCommand("clear", CommandObjectSP(
2985 new CommandObjectTypeFilterClear(interpreter)));
2986 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFilterDelete(
2989 "list", CommandObjectSP(new CommandObjectTypeFilterList(interpreter)));
2992 ~CommandObjectTypeFilter() override = default;
2995 class CommandObjectTypeCategory : public CommandObjectMultiword {
2997 CommandObjectTypeCategory(CommandInterpreter &interpreter)
2998 : CommandObjectMultiword(interpreter, "type category",
2999 "Commands for operating on type categories.",
3000 "type category [<sub-command-options>] ") {
3003 CommandObjectSP(new CommandObjectTypeCategoryDefine(interpreter)));
3006 CommandObjectSP(new CommandObjectTypeCategoryEnable(interpreter)));
3009 CommandObjectSP(new CommandObjectTypeCategoryDisable(interpreter)));
3012 CommandObjectSP(new CommandObjectTypeCategoryDelete(interpreter)));
3013 LoadSubCommand("list", CommandObjectSP(
3014 new CommandObjectTypeCategoryList(interpreter)));
3017 ~CommandObjectTypeCategory() override = default;
3020 class CommandObjectTypeSummary : public CommandObjectMultiword {
3022 CommandObjectTypeSummary(CommandInterpreter &interpreter)
3023 : CommandObjectMultiword(
3024 interpreter, "type summary",
3025 "Commands for editing variable summary display options.",
3026 "type summary [<sub-command-options>] ") {
3028 "add", CommandObjectSP(new CommandObjectTypeSummaryAdd(interpreter)));
3029 LoadSubCommand("clear", CommandObjectSP(new CommandObjectTypeSummaryClear(
3031 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSummaryDelete(
3034 "list", CommandObjectSP(new CommandObjectTypeSummaryList(interpreter)));
3036 "info", CommandObjectSP(new CommandObjectFormatterInfo<TypeSummaryImpl>(
3037 interpreter, "summary",
3038 [](ValueObject &valobj) -> TypeSummaryImpl::SharedPointer {
3039 return valobj.GetSummaryFormat();
3043 ~CommandObjectTypeSummary() override = default;
3046 // CommandObjectType
3048 CommandObjectType::CommandObjectType(CommandInterpreter &interpreter)
3049 : CommandObjectMultiword(interpreter, "type",
3050 "Commands for operating on the type system.",
3051 "type [<sub-command-options>]") {
3052 LoadSubCommand("category",
3053 CommandObjectSP(new CommandObjectTypeCategory(interpreter)));
3054 LoadSubCommand("filter",
3055 CommandObjectSP(new CommandObjectTypeFilter(interpreter)));
3056 LoadSubCommand("format",
3057 CommandObjectSP(new CommandObjectTypeFormat(interpreter)));
3058 LoadSubCommand("summary",
3059 CommandObjectSP(new CommandObjectTypeSummary(interpreter)));
3060 #if LLDB_ENABLE_PYTHON
3061 LoadSubCommand("synthetic",
3062 CommandObjectSP(new CommandObjectTypeSynth(interpreter)));
3064 LoadSubCommand("lookup",
3065 CommandObjectSP(new CommandObjectTypeLookup(interpreter)));
3068 CommandObjectType::~CommandObjectType() = default;