1 //===-- CommandObjectType.cpp -----------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "CommandObjectType.h"
19 #include "lldb/Core/ConstString.h"
20 #include "lldb/Core/Debugger.h"
21 #include "lldb/Core/IOHandler.h"
22 #include "lldb/Core/RegularExpression.h"
23 #include "lldb/Core/State.h"
24 #include "lldb/Core/StringList.h"
25 #include "lldb/DataFormatters/DataVisualization.h"
26 #include "lldb/Interpreter/CommandInterpreter.h"
27 #include "lldb/Interpreter/CommandObject.h"
28 #include "lldb/Interpreter/CommandReturnObject.h"
29 #include "lldb/Interpreter/OptionGroupFormat.h"
30 #include "lldb/Interpreter/OptionValueBoolean.h"
31 #include "lldb/Interpreter/OptionValueLanguage.h"
32 #include "lldb/Interpreter/OptionValueString.h"
33 #include "lldb/Interpreter/Options.h"
34 #include "lldb/Symbol/Symbol.h"
35 #include "lldb/Target/Language.h"
36 #include "lldb/Target/Process.h"
37 #include "lldb/Target/StackFrame.h"
38 #include "lldb/Target/Target.h"
39 #include "lldb/Target/Thread.h"
40 #include "lldb/Target/ThreadList.h"
42 // Other libraries and framework includes
43 #include "llvm/ADT/STLExtras.h"
46 using namespace lldb_private;
48 class ScriptAddOptions {
50 TypeSummaryImpl::Flags m_flags;
51 StringList m_target_types;
54 std::string m_category;
56 ScriptAddOptions(const TypeSummaryImpl::Flags &flags, bool regx,
57 const ConstString &name, std::string catg)
58 : m_flags(flags), m_regex(regx), m_name(name), m_category(catg) {}
60 typedef std::shared_ptr<ScriptAddOptions> SharedPointer;
63 class SynthAddOptions {
66 bool m_skip_references;
69 StringList m_target_types;
70 std::string m_category;
72 SynthAddOptions(bool sptr, bool sref, bool casc, bool regx, std::string catg)
73 : m_skip_pointers(sptr), m_skip_references(sref), m_cascade(casc),
74 m_regex(regx), m_target_types(), m_category(catg) {}
76 typedef std::shared_ptr<SynthAddOptions> SharedPointer;
79 static bool WarnOnPotentialUnquotedUnsignedType(Args &command,
80 CommandReturnObject &result) {
84 for (auto entry : llvm::enumerate(command.entries().drop_back())) {
85 if (entry.Value.ref != "unsigned")
87 auto next = command.entries()[entry.Index + 1].ref;
88 if (next == "int" || next == "short" || next == "char" || next == "long") {
89 result.AppendWarningWithFormat(
90 "unsigned %s being treated as two types. if you meant the combined "
92 "name use quotes, as in \"unsigned %s\"\n",
93 next.str().c_str(), next.str().c_str());
100 static OptionDefinition g_type_summary_add_options[] = {
102 { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Add this to the given category instead of the default one." },
103 { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, cascade through typedef chains." },
104 { LLDB_OPT_SET_ALL, false, "no-value", 'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't show the value, just show the summary, for this type." },
105 { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects." },
106 { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for references-to-type objects." },
107 { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Type names are actually regular expressions." },
108 { LLDB_OPT_SET_1, true, "inline-children", 'c', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "If true, inline all child values into summary string." },
109 { LLDB_OPT_SET_1, false, "omit-names", 'O', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "If true, omit value names in the summary display." },
110 { LLDB_OPT_SET_2, true, "summary-string", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeSummaryString, "Summary string used to display text and object contents." },
111 { LLDB_OPT_SET_3, false, "python-script", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonScript, "Give a one-liner Python script as part of the command." },
112 { LLDB_OPT_SET_3, false, "python-function", 'F', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonFunction, "Give the name of a Python function to use for this type." },
113 { LLDB_OPT_SET_3, false, "input-python", 'P', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Input Python code to use for this type manually." },
114 { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "expand", 'e', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Expand aggregate data types to show children on separate lines." },
115 { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "hide-empty", 'h', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Do not expand aggregate data types with no children." },
116 { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "A name for this summary string." }
120 class CommandObjectTypeSummaryAdd : public CommandObjectParsed,
121 public IOHandlerDelegateMultiline {
123 class CommandOptions : public Options {
125 CommandOptions(CommandInterpreter &interpreter) : Options() {}
127 ~CommandOptions() override = default;
129 Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
130 ExecutionContext *execution_context) override;
132 void OptionParsingStarting(ExecutionContext *execution_context) override;
134 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
135 return llvm::makeArrayRef(g_type_summary_add_options);
138 // Instance variables to hold the values for command options.
140 TypeSummaryImpl::Flags m_flags;
142 std::string m_format_string;
144 std::string m_python_script;
145 std::string m_python_function;
146 bool m_is_add_script;
147 std::string m_category;
150 CommandOptions m_options;
152 Options *GetOptions() override { return &m_options; }
154 bool Execute_ScriptSummary(Args &command, CommandReturnObject &result);
156 bool Execute_StringSummary(Args &command, CommandReturnObject &result);
159 enum SummaryFormatType { eRegularSummary, eRegexSummary, eNamedSummary };
161 CommandObjectTypeSummaryAdd(CommandInterpreter &interpreter);
163 ~CommandObjectTypeSummaryAdd() override = default;
165 void IOHandlerActivated(IOHandler &io_handler) override {
166 static const char *g_summary_addreader_instructions =
167 "Enter your Python command(s). Type 'DONE' to end.\n"
168 "def function (valobj,internal_dict):\n"
169 " \"\"\"valobj: an SBValue which you want to provide a summary "
171 " internal_dict: an LLDB support object not to be used\"\"\"\n";
173 StreamFileSP output_sp(io_handler.GetOutputStreamFile());
175 output_sp->PutCString(g_summary_addreader_instructions);
180 void IOHandlerInputComplete(IOHandler &io_handler,
181 std::string &data) override {
182 StreamFileSP error_sp = io_handler.GetErrorStreamFile();
184 #ifndef LLDB_DISABLE_PYTHON
185 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
188 lines.SplitIntoLines(data);
189 if (lines.GetSize() > 0) {
190 ScriptAddOptions *options_ptr =
191 ((ScriptAddOptions *)io_handler.GetUserData());
193 ScriptAddOptions::SharedPointer options(
194 options_ptr); // this will ensure that we get rid of the pointer
195 // when going out of scope
197 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
199 std::string funct_name_str;
200 if (interpreter->GenerateTypeScriptFunction(lines,
202 if (funct_name_str.empty()) {
203 error_sp->Printf("unable to obtain a valid function name from "
204 "the script interpreter.\n");
207 // now I have a valid function name, let's add this as script
208 // for every type in the list
210 TypeSummaryImplSP script_format;
211 script_format.reset(new ScriptSummaryFormat(
212 options->m_flags, funct_name_str.c_str(),
213 lines.CopyList(" ").c_str()));
217 for (size_t i = 0; i < options->m_target_types.GetSize(); i++) {
218 const char *type_name =
219 options->m_target_types.GetStringAtIndex(i);
220 CommandObjectTypeSummaryAdd::AddSummary(
221 ConstString(type_name), script_format,
223 ? CommandObjectTypeSummaryAdd::eRegexSummary
224 : CommandObjectTypeSummaryAdd::eRegularSummary),
225 options->m_category, &error);
227 error_sp->Printf("error: %s", error.AsCString());
232 if (options->m_name) {
233 CommandObjectTypeSummaryAdd::AddSummary(
234 options->m_name, script_format,
235 CommandObjectTypeSummaryAdd::eNamedSummary,
236 options->m_category, &error);
238 CommandObjectTypeSummaryAdd::AddSummary(
239 options->m_name, script_format,
240 CommandObjectTypeSummaryAdd::eNamedSummary,
241 options->m_category, &error);
243 error_sp->Printf("error: %s", error.AsCString());
247 error_sp->Printf("error: %s", error.AsCString());
251 if (error.AsCString()) {
252 error_sp->Printf("error: %s", error.AsCString());
258 error_sp->Printf("error: unable to generate a function.\n");
262 error_sp->Printf("error: no script interpreter.\n");
266 error_sp->Printf("error: internal synchronization information "
267 "missing or invalid.\n");
271 error_sp->Printf("error: empty function, didn't add python command.\n");
276 "error: script interpreter missing, didn't add python command.\n");
279 #endif // LLDB_DISABLE_PYTHON
280 io_handler.SetIsDone(true);
283 static bool AddSummary(ConstString type_name, lldb::TypeSummaryImplSP entry,
284 SummaryFormatType type, std::string category,
285 Error *error = nullptr);
288 bool DoExecute(Args &command, CommandReturnObject &result) override;
291 static const char *g_synth_addreader_instructions =
292 "Enter your Python command(s). Type 'DONE' to end.\n"
293 "You must define a Python class with these methods:\n"
294 " def __init__(self, valobj, dict):\n"
295 " def num_children(self):\n"
296 " def get_child_at_index(self, index):\n"
297 " def get_child_index(self, name):\n"
298 " def update(self):\n"
300 "class synthProvider:\n";
302 static OptionDefinition g_type_synth_add_options[] = {
304 { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, cascade through typedef chains." },
305 { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects." },
306 { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for references-to-type objects." },
307 { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Add this to the given category instead of the default one." },
308 { LLDB_OPT_SET_2, false, "python-class", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonClass, "Use this Python class to produce synthetic children." },
309 { LLDB_OPT_SET_3, false, "input-python", 'P', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Type Python code to generate a class that provides synthetic children." },
310 { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Type names are actually regular expressions." }
314 class CommandObjectTypeSynthAdd : public CommandObjectParsed,
315 public IOHandlerDelegateMultiline {
317 class CommandOptions : public Options {
319 CommandOptions() : Options() {}
321 ~CommandOptions() override = default;
323 Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
324 ExecutionContext *execution_context) override {
326 const int short_option = m_getopt_table[option_idx].val;
329 switch (short_option) {
331 m_cascade = Args::StringToBoolean(option_arg, true, &success);
333 error.SetErrorStringWithFormat("invalid value for cascade: %s",
334 option_arg.str().c_str());
337 handwrite_python = true;
340 m_class_name = std::string(option_arg);
341 is_class_based = true;
344 m_skip_pointers = true;
347 m_skip_references = true;
350 m_category = std::string(option_arg);
356 error.SetErrorStringWithFormat("unrecognized option '%c'",
364 void OptionParsingStarting(ExecutionContext *execution_context) override {
367 m_skip_pointers = false;
368 m_skip_references = false;
369 m_category = "default";
370 is_class_based = false;
371 handwrite_python = false;
375 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
376 return llvm::makeArrayRef(g_type_synth_add_options);
379 // Instance variables to hold the values for command options.
382 bool m_skip_references;
383 bool m_skip_pointers;
384 std::string m_class_name;
386 std::string m_category;
388 bool handwrite_python;
392 CommandOptions m_options;
394 Options *GetOptions() override { return &m_options; }
396 bool Execute_HandwritePython(Args &command, CommandReturnObject &result);
398 bool Execute_PythonClass(Args &command, CommandReturnObject &result);
401 bool DoExecute(Args &command, CommandReturnObject &result) override {
402 WarnOnPotentialUnquotedUnsignedType(command, result);
404 if (m_options.handwrite_python)
405 return Execute_HandwritePython(command, result);
406 else if (m_options.is_class_based)
407 return Execute_PythonClass(command, result);
409 result.AppendError("must either provide a children list, a Python class "
410 "name, or use -P and type a Python class "
412 result.SetStatus(eReturnStatusFailed);
417 void IOHandlerActivated(IOHandler &io_handler) override {
418 StreamFileSP output_sp(io_handler.GetOutputStreamFile());
420 output_sp->PutCString(g_synth_addreader_instructions);
425 void IOHandlerInputComplete(IOHandler &io_handler,
426 std::string &data) override {
427 StreamFileSP error_sp = io_handler.GetErrorStreamFile();
429 #ifndef LLDB_DISABLE_PYTHON
430 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
433 lines.SplitIntoLines(data);
434 if (lines.GetSize() > 0) {
435 SynthAddOptions *options_ptr =
436 ((SynthAddOptions *)io_handler.GetUserData());
438 SynthAddOptions::SharedPointer options(
439 options_ptr); // this will ensure that we get rid of the pointer
440 // when going out of scope
442 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
444 std::string class_name_str;
445 if (interpreter->GenerateTypeSynthClass(lines, class_name_str)) {
446 if (class_name_str.empty()) {
448 "error: unable to obtain a proper name for the class.\n");
451 // everything should be fine now, let's add the synth provider
454 SyntheticChildrenSP synth_provider;
455 synth_provider.reset(new ScriptedSyntheticChildren(
456 SyntheticChildren::Flags()
457 .SetCascades(options->m_cascade)
458 .SetSkipPointers(options->m_skip_pointers)
459 .SetSkipReferences(options->m_skip_references),
460 class_name_str.c_str()));
462 lldb::TypeCategoryImplSP category;
463 DataVisualization::Categories::GetCategory(
464 ConstString(options->m_category.c_str()), category);
468 for (size_t i = 0; i < options->m_target_types.GetSize(); i++) {
469 const char *type_name =
470 options->m_target_types.GetStringAtIndex(i);
471 ConstString const_type_name(type_name);
472 if (const_type_name) {
473 if (!CommandObjectTypeSynthAdd::AddSynth(
474 const_type_name, synth_provider,
476 ? CommandObjectTypeSynthAdd::eRegexSynth
477 : CommandObjectTypeSynthAdd::eRegularSynth,
478 options->m_category, &error)) {
479 error_sp->Printf("error: %s\n", error.AsCString());
484 error_sp->Printf("error: invalid type name.\n");
491 error_sp->Printf("error: unable to generate a class.\n");
495 error_sp->Printf("error: no script interpreter.\n");
499 error_sp->Printf("error: internal synchronization data missing.\n");
503 error_sp->Printf("error: empty function, didn't add python command.\n");
508 "error: script interpreter missing, didn't add python command.\n");
512 #endif // LLDB_DISABLE_PYTHON
513 io_handler.SetIsDone(true);
517 enum SynthFormatType { eRegularSynth, eRegexSynth };
519 CommandObjectTypeSynthAdd(CommandInterpreter &interpreter);
521 ~CommandObjectTypeSynthAdd() override = default;
523 static bool AddSynth(ConstString type_name, lldb::SyntheticChildrenSP entry,
524 SynthFormatType type, std::string category_name,
528 //-------------------------------------------------------------------------
529 // CommandObjectTypeFormatAdd
530 //-------------------------------------------------------------------------
532 static OptionDefinition g_type_format_add_options[] = {
534 { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Add this to the given category instead of the default one." },
535 { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, cascade through typedef chains." },
536 { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects." },
537 { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for references-to-type objects." },
538 { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Type names are actually regular expressions." },
539 { LLDB_OPT_SET_2, false, "type", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Format variables as if they were of this type." }
543 class CommandObjectTypeFormatAdd : public CommandObjectParsed {
545 class CommandOptions : public OptionGroup {
547 CommandOptions() : OptionGroup() {}
549 ~CommandOptions() override = default;
551 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
552 return llvm::makeArrayRef(g_type_format_add_options);
555 void OptionParsingStarting(ExecutionContext *execution_context) override {
557 m_skip_pointers = false;
558 m_skip_references = false;
560 m_category.assign("default");
561 m_custom_type_name.clear();
564 Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
565 ExecutionContext *execution_context) override {
567 const int short_option =
568 g_type_format_add_options[option_idx].short_option;
571 switch (short_option) {
573 m_cascade = Args::StringToBoolean(option_value, true, &success);
575 error.SetErrorStringWithFormat("invalid value for cascade: %s",
576 option_value.str().c_str());
579 m_skip_pointers = true;
582 m_category.assign(option_value);
585 m_skip_references = true;
591 m_custom_type_name.assign(option_value);
594 error.SetErrorStringWithFormat("unrecognized option '%c'",
602 // Instance variables to hold the values for command options.
605 bool m_skip_references;
606 bool m_skip_pointers;
608 std::string m_category;
609 std::string m_custom_type_name;
612 OptionGroupOptions m_option_group;
613 OptionGroupFormat m_format_options;
614 CommandOptions m_command_options;
616 Options *GetOptions() override { return &m_option_group; }
619 CommandObjectTypeFormatAdd(CommandInterpreter &interpreter)
620 : CommandObjectParsed(interpreter, "type format add",
621 "Add a new formatting style for a type.", nullptr),
622 m_option_group(), m_format_options(eFormatInvalid),
623 m_command_options() {
624 CommandArgumentEntry type_arg;
625 CommandArgumentData type_style_arg;
627 type_style_arg.arg_type = eArgTypeName;
628 type_style_arg.arg_repetition = eArgRepeatPlus;
630 type_arg.push_back(type_style_arg);
632 m_arguments.push_back(type_arg);
636 The following examples of 'type format add' refer to this code snippet for context:
639 typedef float Afloat;
641 typedef Afloat Bfloat;
649 Adding default formatting:
651 (lldb) type format add -f hex AInt
652 (lldb) frame variable iy
655 " Produces hexadecimal display of iy, because no formatter is available for Bint and \
656 the one for Aint is used instead."
659 To prevent this use the cascade option '-C no' to prevent evaluation of typedef chains:
662 (lldb) type format add -f hex -C no AInt
664 Similar reasoning applies to this:
666 (lldb) type format add -f hex -C no float -p
669 " All float values and float references are now formatted as hexadecimal, but not \
670 pointers to floats. Nor will it change the default display for Afloat and Bfloat objects.");
672 // Add the "--format" to all options groups
673 m_option_group.Append(&m_format_options,
674 OptionGroupFormat::OPTION_GROUP_FORMAT,
676 m_option_group.Append(&m_command_options);
677 m_option_group.Finalize();
680 ~CommandObjectTypeFormatAdd() override = default;
683 bool DoExecute(Args &command, CommandReturnObject &result) override {
684 const size_t argc = command.GetArgumentCount();
687 result.AppendErrorWithFormat("%s takes one or more args.\n",
689 result.SetStatus(eReturnStatusFailed);
693 const Format format = m_format_options.GetFormat();
694 if (format == eFormatInvalid &&
695 m_command_options.m_custom_type_name.empty()) {
696 result.AppendErrorWithFormat("%s needs a valid format.\n",
698 result.SetStatus(eReturnStatusFailed);
702 TypeFormatImplSP entry;
704 if (m_command_options.m_custom_type_name.empty())
705 entry.reset(new TypeFormatImpl_Format(
706 format, TypeFormatImpl::Flags()
707 .SetCascades(m_command_options.m_cascade)
708 .SetSkipPointers(m_command_options.m_skip_pointers)
709 .SetSkipReferences(m_command_options.m_skip_references)));
711 entry.reset(new TypeFormatImpl_EnumType(
712 ConstString(m_command_options.m_custom_type_name.c_str()),
713 TypeFormatImpl::Flags()
714 .SetCascades(m_command_options.m_cascade)
715 .SetSkipPointers(m_command_options.m_skip_pointers)
716 .SetSkipReferences(m_command_options.m_skip_references)));
718 // now I have a valid format, let's add it to every type
720 TypeCategoryImplSP category_sp;
721 DataVisualization::Categories::GetCategory(
722 ConstString(m_command_options.m_category), category_sp);
726 WarnOnPotentialUnquotedUnsignedType(command, result);
728 for (auto &arg_entry : command.entries()) {
729 if (arg_entry.ref.empty()) {
730 result.AppendError("empty typenames not allowed");
731 result.SetStatus(eReturnStatusFailed);
735 ConstString typeCS(arg_entry.ref);
736 if (m_command_options.m_regex) {
737 RegularExpressionSP typeRX(new RegularExpression());
738 if (!typeRX->Compile(arg_entry.ref)) {
740 "regex format error (maybe this is not really a regex?)");
741 result.SetStatus(eReturnStatusFailed);
744 category_sp->GetRegexTypeSummariesContainer()->Delete(typeCS);
745 category_sp->GetRegexTypeFormatsContainer()->Add(typeRX, entry);
747 category_sp->GetTypeFormatsContainer()->Add(typeCS, entry);
750 result.SetStatus(eReturnStatusSuccessFinishNoResult);
751 return result.Succeeded();
755 static OptionDefinition g_type_formatter_delete_options[] = {
757 { LLDB_OPT_SET_1, false, "all", 'a', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Delete from every category." },
758 { LLDB_OPT_SET_2, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Delete from given category." },
759 { LLDB_OPT_SET_3, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Delete from given language's category." }
763 class CommandObjectTypeFormatterDelete : public CommandObjectParsed {
765 class CommandOptions : public Options {
767 CommandOptions() : Options() {}
769 ~CommandOptions() override = default;
771 Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
772 ExecutionContext *execution_context) override {
774 const int short_option = m_getopt_table[option_idx].val;
776 switch (short_option) {
781 m_category = std::string(option_arg);
784 m_language = Language::GetLanguageTypeFromString(option_arg);
787 error.SetErrorStringWithFormat("unrecognized option '%c'",
795 void OptionParsingStarting(ExecutionContext *execution_context) override {
796 m_delete_all = false;
797 m_category = "default";
798 m_language = lldb::eLanguageTypeUnknown;
801 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
802 return llvm::makeArrayRef(g_type_formatter_delete_options);
805 // Instance variables to hold the values for command options.
808 std::string m_category;
809 lldb::LanguageType m_language;
812 CommandOptions m_options;
813 uint32_t m_formatter_kind_mask;
815 Options *GetOptions() override { return &m_options; }
818 CommandObjectTypeFormatterDelete(CommandInterpreter &interpreter,
819 uint32_t formatter_kind_mask,
820 const char *name, const char *help)
821 : CommandObjectParsed(interpreter, name, help, nullptr), m_options(),
822 m_formatter_kind_mask(formatter_kind_mask) {
823 CommandArgumentEntry type_arg;
824 CommandArgumentData type_style_arg;
826 type_style_arg.arg_type = eArgTypeName;
827 type_style_arg.arg_repetition = eArgRepeatPlain;
829 type_arg.push_back(type_style_arg);
831 m_arguments.push_back(type_arg);
834 ~CommandObjectTypeFormatterDelete() override = default;
837 virtual bool FormatterSpecificDeletion(ConstString typeCS) { return false; }
839 bool DoExecute(Args &command, CommandReturnObject &result) override {
840 const size_t argc = command.GetArgumentCount();
843 result.AppendErrorWithFormat("%s takes 1 arg.\n", m_cmd_name.c_str());
844 result.SetStatus(eReturnStatusFailed);
848 const char *typeA = command.GetArgumentAtIndex(0);
849 ConstString typeCS(typeA);
852 result.AppendError("empty typenames not allowed");
853 result.SetStatus(eReturnStatusFailed);
857 if (m_options.m_delete_all) {
858 DataVisualization::Categories::ForEach(
859 [this, typeCS](const lldb::TypeCategoryImplSP &category_sp) -> bool {
860 category_sp->Delete(typeCS, m_formatter_kind_mask);
863 result.SetStatus(eReturnStatusSuccessFinishNoResult);
864 return result.Succeeded();
867 bool delete_category = false;
868 bool extra_deletion = false;
870 if (m_options.m_language != lldb::eLanguageTypeUnknown) {
871 lldb::TypeCategoryImplSP category;
872 DataVisualization::Categories::GetCategory(m_options.m_language,
875 delete_category = category->Delete(typeCS, m_formatter_kind_mask);
876 extra_deletion = FormatterSpecificDeletion(typeCS);
878 lldb::TypeCategoryImplSP category;
879 DataVisualization::Categories::GetCategory(
880 ConstString(m_options.m_category.c_str()), category);
882 delete_category = category->Delete(typeCS, m_formatter_kind_mask);
883 extra_deletion = FormatterSpecificDeletion(typeCS);
886 if (delete_category || extra_deletion) {
887 result.SetStatus(eReturnStatusSuccessFinishNoResult);
888 return result.Succeeded();
890 result.AppendErrorWithFormat("no custom formatter for %s.\n", typeA);
891 result.SetStatus(eReturnStatusFailed);
897 static OptionDefinition g_type_formatter_clear_options[] = {
899 { LLDB_OPT_SET_ALL, false, "all", 'a', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Clear every category." }
903 class CommandObjectTypeFormatterClear : public CommandObjectParsed {
905 class CommandOptions : public Options {
907 CommandOptions() : Options() {}
909 ~CommandOptions() override = default;
911 Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
912 ExecutionContext *execution_context) override {
914 const int short_option = m_getopt_table[option_idx].val;
916 switch (short_option) {
921 error.SetErrorStringWithFormat("unrecognized option '%c'",
929 void OptionParsingStarting(ExecutionContext *execution_context) override {
930 m_delete_all = false;
933 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
934 return llvm::makeArrayRef(g_type_formatter_clear_options);
937 // Instance variables to hold the values for command options.
941 CommandOptions m_options;
942 uint32_t m_formatter_kind_mask;
944 Options *GetOptions() override { return &m_options; }
947 CommandObjectTypeFormatterClear(CommandInterpreter &interpreter,
948 uint32_t formatter_kind_mask,
949 const char *name, const char *help)
950 : CommandObjectParsed(interpreter, name, help, nullptr), m_options(),
951 m_formatter_kind_mask(formatter_kind_mask) {}
953 ~CommandObjectTypeFormatterClear() override = default;
956 virtual void FormatterSpecificDeletion() {}
958 bool DoExecute(Args &command, CommandReturnObject &result) override {
959 if (m_options.m_delete_all) {
960 DataVisualization::Categories::ForEach(
961 [this](const TypeCategoryImplSP &category_sp) -> bool {
962 category_sp->Clear(m_formatter_kind_mask);
966 lldb::TypeCategoryImplSP category;
967 if (command.GetArgumentCount() > 0) {
968 const char *cat_name = command.GetArgumentAtIndex(0);
969 ConstString cat_nameCS(cat_name);
970 DataVisualization::Categories::GetCategory(cat_nameCS, category);
972 DataVisualization::Categories::GetCategory(ConstString(nullptr),
975 category->Clear(m_formatter_kind_mask);
978 FormatterSpecificDeletion();
980 result.SetStatus(eReturnStatusSuccessFinishResult);
981 return result.Succeeded();
985 //-------------------------------------------------------------------------
986 // CommandObjectTypeFormatDelete
987 //-------------------------------------------------------------------------
989 class CommandObjectTypeFormatDelete : public CommandObjectTypeFormatterDelete {
991 CommandObjectTypeFormatDelete(CommandInterpreter &interpreter)
992 : CommandObjectTypeFormatterDelete(
994 eFormatCategoryItemValue | eFormatCategoryItemRegexValue,
995 "type format delete",
996 "Delete an existing formatting style for a type.") {}
998 ~CommandObjectTypeFormatDelete() override = default;
1001 //-------------------------------------------------------------------------
1002 // CommandObjectTypeFormatClear
1003 //-------------------------------------------------------------------------
1005 class CommandObjectTypeFormatClear : public CommandObjectTypeFormatterClear {
1007 CommandObjectTypeFormatClear(CommandInterpreter &interpreter)
1008 : CommandObjectTypeFormatterClear(
1010 eFormatCategoryItemValue | eFormatCategoryItemRegexValue,
1011 "type format clear", "Delete all existing format styles.") {}
1014 template <typename FormatterType>
1015 class CommandObjectTypeFormatterList : public CommandObjectParsed {
1016 typedef typename FormatterType::SharedPointer FormatterSharedPointer;
1018 class CommandOptions : public Options {
1021 : Options(), m_category_regex("", ""),
1022 m_category_language(lldb::eLanguageTypeUnknown,
1023 lldb::eLanguageTypeUnknown) {}
1025 ~CommandOptions() override = default;
1027 Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1028 ExecutionContext *execution_context) override {
1030 const int short_option = m_getopt_table[option_idx].val;
1031 switch (short_option) {
1033 m_category_regex.SetCurrentValue(option_arg);
1034 m_category_regex.SetOptionWasSet();
1037 error = m_category_language.SetValueFromString(option_arg);
1038 if (error.Success())
1039 m_category_language.SetOptionWasSet();
1042 error.SetErrorStringWithFormat("unrecognized option '%c'",
1050 void OptionParsingStarting(ExecutionContext *execution_context) override {
1051 m_category_regex.Clear();
1052 m_category_language.Clear();
1055 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1056 static OptionDefinition g_option_table[] = {
1058 {LLDB_OPT_SET_1, false, "category-regex", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Only show categories matching this filter."},
1059 {LLDB_OPT_SET_2, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Only show the category for a specific language."}
1062 return llvm::ArrayRef<OptionDefinition>(g_option_table);
1065 // Instance variables to hold the values for command options.
1067 OptionValueString m_category_regex;
1068 OptionValueLanguage m_category_language;
1071 CommandOptions m_options;
1073 Options *GetOptions() override { return &m_options; }
1076 CommandObjectTypeFormatterList(CommandInterpreter &interpreter,
1077 const char *name, const char *help)
1078 : CommandObjectParsed(interpreter, name, help, nullptr), m_options() {
1079 CommandArgumentEntry type_arg;
1080 CommandArgumentData type_style_arg;
1082 type_style_arg.arg_type = eArgTypeName;
1083 type_style_arg.arg_repetition = eArgRepeatOptional;
1085 type_arg.push_back(type_style_arg);
1087 m_arguments.push_back(type_arg);
1090 ~CommandObjectTypeFormatterList() override = default;
1093 virtual bool FormatterSpecificList(CommandReturnObject &result) {
1097 bool DoExecute(Args &command, CommandReturnObject &result) override {
1098 const size_t argc = command.GetArgumentCount();
1100 std::unique_ptr<RegularExpression> category_regex;
1101 std::unique_ptr<RegularExpression> formatter_regex;
1103 if (m_options.m_category_regex.OptionWasSet()) {
1104 category_regex.reset(new RegularExpression());
1105 if (!category_regex->Compile(
1106 m_options.m_category_regex.GetCurrentValueAsRef())) {
1107 result.AppendErrorWithFormat(
1108 "syntax error in category regular expression '%s'",
1109 m_options.m_category_regex.GetCurrentValueAsRef().str().c_str());
1110 result.SetStatus(eReturnStatusFailed);
1116 const char *arg = command.GetArgumentAtIndex(0);
1117 formatter_regex.reset(new RegularExpression());
1118 if (!formatter_regex->Compile(llvm::StringRef::withNullAsEmpty(arg))) {
1119 result.AppendErrorWithFormat("syntax error in regular expression '%s'",
1121 result.SetStatus(eReturnStatusFailed);
1126 bool any_printed = false;
1128 auto category_closure = [&result, &formatter_regex, &any_printed](
1129 const lldb::TypeCategoryImplSP &category) -> void {
1130 result.GetOutputStream().Printf(
1131 "-----------------------\nCategory: %s%s\n-----------------------\n",
1132 category->GetName(), category->IsEnabled() ? "" : " (disabled)");
1134 TypeCategoryImpl::ForEachCallbacks<FormatterType> foreach;
1136 .SetExact([&result, &formatter_regex, &any_printed](
1138 const FormatterSharedPointer &format_sp) -> bool {
1139 if (formatter_regex) {
1141 if (name.GetStringRef() == formatter_regex->GetText()) {
1143 } else if (formatter_regex->Execute(name.GetStringRef())) {
1152 result.GetOutputStream().Printf("%s: %s\n", name.AsCString(),
1153 format_sp->GetDescription().c_str());
1158 .SetWithRegex([&result, &formatter_regex, &any_printed](
1159 RegularExpressionSP regex_sp,
1160 const FormatterSharedPointer &format_sp) -> bool {
1161 if (formatter_regex) {
1163 if (regex_sp->GetText() == formatter_regex->GetText()) {
1165 } else if (formatter_regex->Execute(regex_sp->GetText())) {
1174 result.GetOutputStream().Printf("%s: %s\n",
1175 regex_sp->GetText().str().c_str(),
1176 format_sp->GetDescription().c_str());
1180 category->ForEach(foreach);
1183 if (m_options.m_category_language.OptionWasSet()) {
1184 lldb::TypeCategoryImplSP category_sp;
1185 DataVisualization::Categories::GetCategory(
1186 m_options.m_category_language.GetCurrentValue(), category_sp);
1188 category_closure(category_sp);
1190 DataVisualization::Categories::ForEach(
1191 [this, &command, &result, &category_regex, &formatter_regex,
1193 const lldb::TypeCategoryImplSP &category) -> bool {
1194 if (category_regex) {
1196 if (category->GetName() == category_regex->GetText()) {
1198 } else if (category_regex->Execute(
1199 llvm::StringRef::withNullAsEmpty(
1200 category->GetName()))) {
1208 category_closure(category);
1213 any_printed = FormatterSpecificList(result) | any_printed;
1217 result.SetStatus(eReturnStatusSuccessFinishResult);
1219 result.GetOutputStream().PutCString("no matching results found.\n");
1220 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1222 return result.Succeeded();
1226 //-------------------------------------------------------------------------
1227 // CommandObjectTypeFormatList
1228 //-------------------------------------------------------------------------
1230 class CommandObjectTypeFormatList
1231 : public CommandObjectTypeFormatterList<TypeFormatImpl> {
1233 CommandObjectTypeFormatList(CommandInterpreter &interpreter)
1234 : CommandObjectTypeFormatterList(interpreter, "type format list",
1235 "Show a list of current formats.") {}
1238 #ifndef LLDB_DISABLE_PYTHON
1240 //-------------------------------------------------------------------------
1241 // CommandObjectTypeSummaryAdd
1242 //-------------------------------------------------------------------------
1244 #endif // LLDB_DISABLE_PYTHON
1246 Error CommandObjectTypeSummaryAdd::CommandOptions::SetOptionValue(
1247 uint32_t option_idx, llvm::StringRef option_arg,
1248 ExecutionContext *execution_context) {
1250 const int short_option = m_getopt_table[option_idx].val;
1253 switch (short_option) {
1255 m_flags.SetCascades(Args::StringToBoolean(option_arg, true, &success));
1257 error.SetErrorStringWithFormat("invalid value for cascade: %s",
1258 option_arg.str().c_str());
1261 m_flags.SetDontShowChildren(false);
1264 m_flags.SetHideEmptyAggregates(true);
1267 m_flags.SetDontShowValue(true);
1270 m_flags.SetShowMembersOneLiner(true);
1273 m_format_string = std::string(option_arg);
1276 m_flags.SetSkipPointers(true);
1279 m_flags.SetSkipReferences(true);
1285 m_name.SetString(option_arg);
1288 m_python_script = option_arg;
1289 m_is_add_script = true;
1292 m_python_function = option_arg;
1293 m_is_add_script = true;
1296 m_is_add_script = true;
1299 m_category = std::string(option_arg);
1302 m_flags.SetHideItemNames(true);
1305 error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
1312 void CommandObjectTypeSummaryAdd::CommandOptions::OptionParsingStarting(
1313 ExecutionContext *execution_context) {
1314 m_flags.Clear().SetCascades().SetDontShowChildren().SetDontShowValue(false);
1315 m_flags.SetShowMembersOneLiner(false)
1316 .SetSkipPointers(false)
1317 .SetSkipReferences(false)
1318 .SetHideItemNames(false);
1322 m_python_script = "";
1323 m_python_function = "";
1324 m_format_string = "";
1325 m_is_add_script = false;
1326 m_category = "default";
1329 #ifndef LLDB_DISABLE_PYTHON
1331 bool CommandObjectTypeSummaryAdd::Execute_ScriptSummary(
1332 Args &command, CommandReturnObject &result) {
1333 const size_t argc = command.GetArgumentCount();
1335 if (argc < 1 && !m_options.m_name) {
1336 result.AppendErrorWithFormat("%s takes one or more args.\n",
1337 m_cmd_name.c_str());
1338 result.SetStatus(eReturnStatusFailed);
1342 TypeSummaryImplSP script_format;
1344 if (!m_options.m_python_function
1345 .empty()) // we have a Python function ready to use
1347 const char *funct_name = m_options.m_python_function.c_str();
1348 if (!funct_name || !funct_name[0]) {
1349 result.AppendError("function name empty.\n");
1350 result.SetStatus(eReturnStatusFailed);
1355 (" " + m_options.m_python_function + "(valobj,internal_dict)");
1357 script_format.reset(
1358 new ScriptSummaryFormat(m_options.m_flags, funct_name, code.c_str()));
1360 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
1362 if (interpreter && !interpreter->CheckObjectExists(funct_name))
1363 result.AppendWarningWithFormat(
1364 "The provided function \"%s\" does not exist - "
1365 "please define it before attempting to use this summary.\n",
1367 } else if (!m_options.m_python_script
1368 .empty()) // we have a quick 1-line script, just use it
1370 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
1372 result.AppendError("script interpreter missing - unable to generate "
1373 "function wrapper.\n");
1374 result.SetStatus(eReturnStatusFailed);
1377 StringList funct_sl;
1378 funct_sl << m_options.m_python_script.c_str();
1379 std::string funct_name_str;
1380 if (!interpreter->GenerateTypeScriptFunction(funct_sl, funct_name_str)) {
1381 result.AppendError("unable to generate function wrapper.\n");
1382 result.SetStatus(eReturnStatusFailed);
1385 if (funct_name_str.empty()) {
1387 "script interpreter failed to generate a valid function name.\n");
1388 result.SetStatus(eReturnStatusFailed);
1392 std::string code = " " + m_options.m_python_script;
1394 script_format.reset(new ScriptSummaryFormat(
1395 m_options.m_flags, funct_name_str.c_str(), code.c_str()));
1397 // Use an IOHandler to grab Python code from the user
1398 ScriptAddOptions *options =
1399 new ScriptAddOptions(m_options.m_flags, m_options.m_regex,
1400 m_options.m_name, m_options.m_category);
1402 for (auto &entry : command.entries()) {
1403 if (entry.ref.empty()) {
1404 result.AppendError("empty typenames not allowed");
1405 result.SetStatus(eReturnStatusFailed);
1409 options->m_target_types << entry.ref;
1412 m_interpreter.GetPythonCommandsFromIOHandler(
1414 *this, // IOHandlerDelegate
1415 true, // Run IOHandler in async mode
1416 options); // Baton for the "io_handler" that will be passed back into
1417 // our IOHandlerDelegate functions
1418 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1420 return result.Succeeded();
1423 // if I am here, script_format must point to something good, so I can add that
1424 // as a script summary to all interested parties
1428 for (auto &entry : command.entries()) {
1429 CommandObjectTypeSummaryAdd::AddSummary(
1430 ConstString(entry.ref), script_format,
1431 (m_options.m_regex ? eRegexSummary : eRegularSummary),
1432 m_options.m_category, &error);
1434 result.AppendError(error.AsCString());
1435 result.SetStatus(eReturnStatusFailed);
1440 if (m_options.m_name) {
1441 AddSummary(m_options.m_name, script_format, eNamedSummary,
1442 m_options.m_category, &error);
1444 result.AppendError(error.AsCString());
1445 result.AppendError("added to types, but not given a name");
1446 result.SetStatus(eReturnStatusFailed);
1451 return result.Succeeded();
1454 #endif // LLDB_DISABLE_PYTHON
1456 bool CommandObjectTypeSummaryAdd::Execute_StringSummary(
1457 Args &command, CommandReturnObject &result) {
1458 const size_t argc = command.GetArgumentCount();
1460 if (argc < 1 && !m_options.m_name) {
1461 result.AppendErrorWithFormat("%s takes one or more args.\n",
1462 m_cmd_name.c_str());
1463 result.SetStatus(eReturnStatusFailed);
1467 if (!m_options.m_flags.GetShowMembersOneLiner() &&
1468 m_options.m_format_string.empty()) {
1469 result.AppendError("empty summary strings not allowed");
1470 result.SetStatus(eReturnStatusFailed);
1474 const char *format_cstr = (m_options.m_flags.GetShowMembersOneLiner()
1476 : m_options.m_format_string.c_str());
1478 // ${var%S} is an endless recursion, prevent it
1479 if (strcmp(format_cstr, "${var%S}") == 0) {
1480 result.AppendError("recursive summary not allowed");
1481 result.SetStatus(eReturnStatusFailed);
1485 std::unique_ptr<StringSummaryFormat> string_format(
1486 new StringSummaryFormat(m_options.m_flags, format_cstr));
1487 if (!string_format) {
1488 result.AppendError("summary creation failed");
1489 result.SetStatus(eReturnStatusFailed);
1492 if (string_format->m_error.Fail()) {
1493 result.AppendErrorWithFormat("syntax error: %s",
1494 string_format->m_error.AsCString("<unknown>"));
1495 result.SetStatus(eReturnStatusFailed);
1498 lldb::TypeSummaryImplSP entry(string_format.release());
1500 // now I have a valid format, let's add it to every type
1502 for (auto &arg_entry : command.entries()) {
1503 if (arg_entry.ref.empty()) {
1504 result.AppendError("empty typenames not allowed");
1505 result.SetStatus(eReturnStatusFailed);
1508 ConstString typeCS(arg_entry.ref);
1510 AddSummary(typeCS, entry,
1511 (m_options.m_regex ? eRegexSummary : eRegularSummary),
1512 m_options.m_category, &error);
1515 result.AppendError(error.AsCString());
1516 result.SetStatus(eReturnStatusFailed);
1521 if (m_options.m_name) {
1522 AddSummary(m_options.m_name, entry, eNamedSummary, m_options.m_category,
1525 result.AppendError(error.AsCString());
1526 result.AppendError("added to types, but not given a name");
1527 result.SetStatus(eReturnStatusFailed);
1532 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1533 return result.Succeeded();
1536 CommandObjectTypeSummaryAdd::CommandObjectTypeSummaryAdd(
1537 CommandInterpreter &interpreter)
1538 : CommandObjectParsed(interpreter, "type summary add",
1539 "Add a new summary style for a type.", nullptr),
1540 IOHandlerDelegateMultiline("DONE"), m_options(interpreter) {
1541 CommandArgumentEntry type_arg;
1542 CommandArgumentData type_style_arg;
1544 type_style_arg.arg_type = eArgTypeName;
1545 type_style_arg.arg_repetition = eArgRepeatPlus;
1547 type_arg.push_back(type_style_arg);
1549 m_arguments.push_back(type_arg);
1553 The following examples of 'type summary add' refer to this code snippet for context:
1559 JustADemo(int p = 1, float v = 0.1) : ptr(new int(p)), value(v) {}
1561 JustADemo demo_instance(42, 3.14);
1563 typedef JustADemo NewDemo;
1564 NewDemo new_demo_instance(42, 3.14);
1566 (lldb) type summary add --summary-string "the answer is ${*var.ptr}" JustADemo
1568 Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42"
1570 (lldb) type summary add --summary-string "the answer is ${*var.ptr}, and the question is ${var.value}" JustADemo
1572 Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42 and the question is 3.14"
1575 "Alternatively, you could define formatting for all pointers to integers and \
1576 rely on that when formatting JustADemo to obtain the same result:"
1579 (lldb) type summary add --summary-string "${var%V} -> ${*var}" "int *"
1580 (lldb) type summary add --summary-string "the answer is ${var.ptr}, and the question is ${var.value}" JustADemo
1583 "Type summaries are automatically applied to derived typedefs, so the examples \
1584 above apply to both JustADemo and NewDemo. The cascade option can be used to \
1585 suppress this behavior:"
1588 (lldb) type summary add --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo -C no
1590 The summary will now be used for values of JustADemo but not NewDemo.
1593 "By default summaries are shown for pointers and references to values of the \
1594 specified type. To suppress formatting for pointers use the -p option, or apply \
1595 the corresponding -r option to suppress formatting for references:"
1598 (lldb) type summary add -p -r --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo
1601 "One-line summaries including all fields in a type can be inferred without supplying an \
1602 explicit summary string by passing the -c option:"
1605 (lldb) type summary add -c JustADemo
1606 (lldb) frame variable demo_instance
1607 (ptr=<address>, value=3.14)
1610 "Type summaries normally suppress the nested display of individual fields. To \
1611 supply a summary to supplement the default structure add the -e option:"
1614 (lldb) type summary add -e --summary-string "*ptr = ${*var.ptr}" JustADemo
1617 "Now when displaying JustADemo values the int* is displayed, followed by the \
1618 standard LLDB sequence of children, one per line:"
1627 "You can also add summaries written in Python. These scripts use lldb public API to \
1628 gather information from your variables and produce a meaningful summary. To start a \
1629 multi-line script use the -P option. The function declaration will be displayed along with \
1630 a comment describing the two arguments. End your script with the word 'DONE' on a line by \
1634 (lldb) type summary add JustADemo -P
1635 def function (valobj,internal_dict):
1636 """valobj: an SBValue which you want to provide a summary for
1637 internal_dict: an LLDB support object not to be used"""
1638 value = valobj.GetChildMemberWithName('value');
1639 return 'My value is ' + value.GetValue();
1642 Alternatively, the -o option can be used when providing a simple one-line Python script:
1644 (lldb) type summary add JustADemo -o "value = valobj.GetChildMemberWithName('value'); return 'My value is ' + value.GetValue();")");
1647 bool CommandObjectTypeSummaryAdd::DoExecute(Args &command,
1648 CommandReturnObject &result) {
1649 WarnOnPotentialUnquotedUnsignedType(command, result);
1651 if (m_options.m_is_add_script) {
1652 #ifndef LLDB_DISABLE_PYTHON
1653 return Execute_ScriptSummary(command, result);
1655 result.AppendError("python is disabled");
1656 result.SetStatus(eReturnStatusFailed);
1658 #endif // LLDB_DISABLE_PYTHON
1661 return Execute_StringSummary(command, result);
1664 static bool FixArrayTypeNameWithRegex(ConstString &type_name) {
1665 llvm::StringRef type_name_ref(type_name.GetStringRef());
1667 if (type_name_ref.endswith("[]")) {
1668 std::string type_name_str(type_name.GetCString());
1669 type_name_str.resize(type_name_str.length() - 2);
1670 if (type_name_str.back() != ' ')
1671 type_name_str.append(" \\[[0-9]+\\]");
1673 type_name_str.append("\\[[0-9]+\\]");
1674 type_name.SetCString(type_name_str.c_str());
1680 bool CommandObjectTypeSummaryAdd::AddSummary(ConstString type_name,
1681 TypeSummaryImplSP entry,
1682 SummaryFormatType type,
1683 std::string category_name,
1685 lldb::TypeCategoryImplSP category;
1686 DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()),
1689 if (type == eRegularSummary) {
1690 if (FixArrayTypeNameWithRegex(type_name))
1691 type = eRegexSummary;
1694 if (type == eRegexSummary) {
1695 RegularExpressionSP typeRX(new RegularExpression());
1696 if (!typeRX->Compile(type_name.GetStringRef())) {
1698 error->SetErrorString(
1699 "regex format error (maybe this is not really a regex?)");
1703 category->GetRegexTypeSummariesContainer()->Delete(type_name);
1704 category->GetRegexTypeSummariesContainer()->Add(typeRX, entry);
1707 } else if (type == eNamedSummary) {
1708 // system named summaries do not exist (yet?)
1709 DataVisualization::NamedSummaryFormats::Add(type_name, entry);
1712 category->GetTypeSummariesContainer()->Add(type_name, entry);
1717 //-------------------------------------------------------------------------
1718 // CommandObjectTypeSummaryDelete
1719 //-------------------------------------------------------------------------
1721 class CommandObjectTypeSummaryDelete : public CommandObjectTypeFormatterDelete {
1723 CommandObjectTypeSummaryDelete(CommandInterpreter &interpreter)
1724 : CommandObjectTypeFormatterDelete(
1726 eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary,
1727 "type summary delete", "Delete an existing summary for a type.") {}
1729 ~CommandObjectTypeSummaryDelete() override = default;
1732 bool FormatterSpecificDeletion(ConstString typeCS) override {
1733 if (m_options.m_language != lldb::eLanguageTypeUnknown)
1735 return DataVisualization::NamedSummaryFormats::Delete(typeCS);
1739 class CommandObjectTypeSummaryClear : public CommandObjectTypeFormatterClear {
1741 CommandObjectTypeSummaryClear(CommandInterpreter &interpreter)
1742 : CommandObjectTypeFormatterClear(
1744 eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary,
1745 "type summary clear", "Delete all existing summaries.") {}
1748 void FormatterSpecificDeletion() override {
1749 DataVisualization::NamedSummaryFormats::Clear();
1753 //-------------------------------------------------------------------------
1754 // CommandObjectTypeSummaryList
1755 //-------------------------------------------------------------------------
1757 class CommandObjectTypeSummaryList
1758 : public CommandObjectTypeFormatterList<TypeSummaryImpl> {
1760 CommandObjectTypeSummaryList(CommandInterpreter &interpreter)
1761 : CommandObjectTypeFormatterList(interpreter, "type summary list",
1762 "Show a list of current summaries.") {}
1765 bool FormatterSpecificList(CommandReturnObject &result) override {
1766 if (DataVisualization::NamedSummaryFormats::GetCount() > 0) {
1767 result.GetOutputStream().Printf("Named summaries:\n");
1768 DataVisualization::NamedSummaryFormats::ForEach(
1769 [&result](ConstString name,
1770 const TypeSummaryImplSP &summary_sp) -> bool {
1771 result.GetOutputStream().Printf(
1772 "%s: %s\n", name.AsCString(),
1773 summary_sp->GetDescription().c_str());
1782 //-------------------------------------------------------------------------
1783 // CommandObjectTypeCategoryDefine
1784 //-------------------------------------------------------------------------
1786 static OptionDefinition g_type_category_define_options[] = {
1788 { LLDB_OPT_SET_ALL, false, "enabled", 'e', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "If specified, this category will be created enabled." },
1789 { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Specify the language that this category is supported for." }
1793 class CommandObjectTypeCategoryDefine : public CommandObjectParsed {
1794 class CommandOptions : public Options {
1797 : Options(), m_define_enabled(false, false),
1798 m_cate_language(eLanguageTypeUnknown, eLanguageTypeUnknown) {}
1800 ~CommandOptions() override = default;
1802 Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1803 ExecutionContext *execution_context) override {
1805 const int short_option = m_getopt_table[option_idx].val;
1807 switch (short_option) {
1809 m_define_enabled.SetValueFromString(llvm::StringRef("true"));
1812 error = m_cate_language.SetValueFromString(option_arg);
1815 error.SetErrorStringWithFormat("unrecognized option '%c'",
1823 void OptionParsingStarting(ExecutionContext *execution_context) override {
1824 m_define_enabled.Clear();
1825 m_cate_language.Clear();
1828 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1829 return llvm::makeArrayRef(g_type_category_define_options);
1832 // Instance variables to hold the values for command options.
1834 OptionValueBoolean m_define_enabled;
1835 OptionValueLanguage m_cate_language;
1838 CommandOptions m_options;
1840 Options *GetOptions() override { return &m_options; }
1843 CommandObjectTypeCategoryDefine(CommandInterpreter &interpreter)
1844 : CommandObjectParsed(interpreter, "type category define",
1845 "Define a new category as a source of formatters.",
1848 CommandArgumentEntry type_arg;
1849 CommandArgumentData type_style_arg;
1851 type_style_arg.arg_type = eArgTypeName;
1852 type_style_arg.arg_repetition = eArgRepeatPlus;
1854 type_arg.push_back(type_style_arg);
1856 m_arguments.push_back(type_arg);
1859 ~CommandObjectTypeCategoryDefine() override = default;
1862 bool DoExecute(Args &command, CommandReturnObject &result) override {
1863 const size_t argc = command.GetArgumentCount();
1866 result.AppendErrorWithFormat("%s takes 1 or more args.\n",
1867 m_cmd_name.c_str());
1868 result.SetStatus(eReturnStatusFailed);
1872 for (auto &entry : command.entries()) {
1873 TypeCategoryImplSP category_sp;
1874 if (DataVisualization::Categories::GetCategory(ConstString(entry.ref),
1877 category_sp->AddLanguage(m_options.m_cate_language.GetCurrentValue());
1878 if (m_options.m_define_enabled.GetCurrentValue())
1879 DataVisualization::Categories::Enable(category_sp,
1880 TypeCategoryMap::Default);
1884 result.SetStatus(eReturnStatusSuccessFinishResult);
1885 return result.Succeeded();
1889 //-------------------------------------------------------------------------
1890 // CommandObjectTypeCategoryEnable
1891 //-------------------------------------------------------------------------
1893 static OptionDefinition g_type_category_enable_options[] = {
1895 { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Enable the category for this language." },
1899 class CommandObjectTypeCategoryEnable : public CommandObjectParsed {
1900 class CommandOptions : public Options {
1902 CommandOptions() : Options() {}
1904 ~CommandOptions() override = default;
1906 Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1907 ExecutionContext *execution_context) override {
1909 const int short_option = m_getopt_table[option_idx].val;
1911 switch (short_option) {
1913 if (!option_arg.empty()) {
1914 m_language = Language::GetLanguageTypeFromString(option_arg);
1915 if (m_language == lldb::eLanguageTypeUnknown)
1916 error.SetErrorStringWithFormat("unrecognized language '%s'",
1917 option_arg.str().c_str());
1921 error.SetErrorStringWithFormat("unrecognized option '%c'",
1929 void OptionParsingStarting(ExecutionContext *execution_context) override {
1930 m_language = lldb::eLanguageTypeUnknown;
1933 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1934 return llvm::makeArrayRef(g_type_category_enable_options);
1937 // Instance variables to hold the values for command options.
1939 lldb::LanguageType m_language;
1942 CommandOptions m_options;
1944 Options *GetOptions() override { return &m_options; }
1947 CommandObjectTypeCategoryEnable(CommandInterpreter &interpreter)
1948 : CommandObjectParsed(interpreter, "type category enable",
1949 "Enable a category as a source of formatters.",
1952 CommandArgumentEntry type_arg;
1953 CommandArgumentData type_style_arg;
1955 type_style_arg.arg_type = eArgTypeName;
1956 type_style_arg.arg_repetition = eArgRepeatPlus;
1958 type_arg.push_back(type_style_arg);
1960 m_arguments.push_back(type_arg);
1963 ~CommandObjectTypeCategoryEnable() override = default;
1966 bool DoExecute(Args &command, CommandReturnObject &result) override {
1967 const size_t argc = command.GetArgumentCount();
1969 if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) {
1970 result.AppendErrorWithFormat("%s takes arguments and/or a language",
1971 m_cmd_name.c_str());
1972 result.SetStatus(eReturnStatusFailed);
1976 if (argc == 1 && strcmp(command.GetArgumentAtIndex(0), "*") == 0) {
1977 DataVisualization::Categories::EnableStar();
1978 } else if (argc > 0) {
1979 for (int i = argc - 1; i >= 0; i--) {
1980 const char *typeA = command.GetArgumentAtIndex(i);
1981 ConstString typeCS(typeA);
1984 result.AppendError("empty category name not allowed");
1985 result.SetStatus(eReturnStatusFailed);
1988 DataVisualization::Categories::Enable(typeCS);
1989 lldb::TypeCategoryImplSP cate;
1990 if (DataVisualization::Categories::GetCategory(typeCS, cate) && cate) {
1991 if (cate->GetCount() == 0) {
1992 result.AppendWarning("empty category enabled (typo?)");
1998 if (m_options.m_language != lldb::eLanguageTypeUnknown)
1999 DataVisualization::Categories::Enable(m_options.m_language);
2001 result.SetStatus(eReturnStatusSuccessFinishResult);
2002 return result.Succeeded();
2006 //-------------------------------------------------------------------------
2007 // CommandObjectTypeCategoryDelete
2008 //-------------------------------------------------------------------------
2010 class CommandObjectTypeCategoryDelete : public CommandObjectParsed {
2012 CommandObjectTypeCategoryDelete(CommandInterpreter &interpreter)
2013 : CommandObjectParsed(interpreter, "type category delete",
2014 "Delete a category and all associated formatters.",
2016 CommandArgumentEntry type_arg;
2017 CommandArgumentData type_style_arg;
2019 type_style_arg.arg_type = eArgTypeName;
2020 type_style_arg.arg_repetition = eArgRepeatPlus;
2022 type_arg.push_back(type_style_arg);
2024 m_arguments.push_back(type_arg);
2027 ~CommandObjectTypeCategoryDelete() override = default;
2030 bool DoExecute(Args &command, CommandReturnObject &result) override {
2031 const size_t argc = command.GetArgumentCount();
2034 result.AppendErrorWithFormat("%s takes 1 or more arg.\n",
2035 m_cmd_name.c_str());
2036 result.SetStatus(eReturnStatusFailed);
2040 bool success = true;
2042 // the order is not relevant here
2043 for (int i = argc - 1; i >= 0; i--) {
2044 const char *typeA = command.GetArgumentAtIndex(i);
2045 ConstString typeCS(typeA);
2048 result.AppendError("empty category name not allowed");
2049 result.SetStatus(eReturnStatusFailed);
2052 if (!DataVisualization::Categories::Delete(typeCS))
2053 success = false; // keep deleting even if we hit an error
2056 result.SetStatus(eReturnStatusSuccessFinishResult);
2057 return result.Succeeded();
2059 result.AppendError("cannot delete one or more categories\n");
2060 result.SetStatus(eReturnStatusFailed);
2066 //-------------------------------------------------------------------------
2067 // CommandObjectTypeCategoryDisable
2068 //-------------------------------------------------------------------------
2070 OptionDefinition g_type_category_disable_options[] = {
2072 { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Enable the category for this language." }
2076 class CommandObjectTypeCategoryDisable : public CommandObjectParsed {
2077 class CommandOptions : public Options {
2079 CommandOptions() : Options() {}
2081 ~CommandOptions() override = default;
2083 Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2084 ExecutionContext *execution_context) override {
2086 const int short_option = m_getopt_table[option_idx].val;
2088 switch (short_option) {
2090 if (!option_arg.empty()) {
2091 m_language = Language::GetLanguageTypeFromString(option_arg);
2092 if (m_language == lldb::eLanguageTypeUnknown)
2093 error.SetErrorStringWithFormat("unrecognized language '%s'",
2094 option_arg.str().c_str());
2098 error.SetErrorStringWithFormat("unrecognized option '%c'",
2106 void OptionParsingStarting(ExecutionContext *execution_context) override {
2107 m_language = lldb::eLanguageTypeUnknown;
2110 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2111 return llvm::makeArrayRef(g_type_category_disable_options);
2114 // Instance variables to hold the values for command options.
2116 lldb::LanguageType m_language;
2119 CommandOptions m_options;
2121 Options *GetOptions() override { return &m_options; }
2124 CommandObjectTypeCategoryDisable(CommandInterpreter &interpreter)
2125 : CommandObjectParsed(interpreter, "type category disable",
2126 "Disable a category as a source of formatters.",
2129 CommandArgumentEntry type_arg;
2130 CommandArgumentData type_style_arg;
2132 type_style_arg.arg_type = eArgTypeName;
2133 type_style_arg.arg_repetition = eArgRepeatPlus;
2135 type_arg.push_back(type_style_arg);
2137 m_arguments.push_back(type_arg);
2140 ~CommandObjectTypeCategoryDisable() override = default;
2143 bool DoExecute(Args &command, CommandReturnObject &result) override {
2144 const size_t argc = command.GetArgumentCount();
2146 if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) {
2147 result.AppendErrorWithFormat("%s takes arguments and/or a language",
2148 m_cmd_name.c_str());
2149 result.SetStatus(eReturnStatusFailed);
2153 if (argc == 1 && strcmp(command.GetArgumentAtIndex(0), "*") == 0) {
2154 DataVisualization::Categories::DisableStar();
2155 } else if (argc > 0) {
2156 // the order is not relevant here
2157 for (int i = argc - 1; i >= 0; i--) {
2158 const char *typeA = command.GetArgumentAtIndex(i);
2159 ConstString typeCS(typeA);
2162 result.AppendError("empty category name not allowed");
2163 result.SetStatus(eReturnStatusFailed);
2166 DataVisualization::Categories::Disable(typeCS);
2170 if (m_options.m_language != lldb::eLanguageTypeUnknown)
2171 DataVisualization::Categories::Disable(m_options.m_language);
2173 result.SetStatus(eReturnStatusSuccessFinishResult);
2174 return result.Succeeded();
2178 //-------------------------------------------------------------------------
2179 // CommandObjectTypeCategoryList
2180 //-------------------------------------------------------------------------
2182 class CommandObjectTypeCategoryList : public CommandObjectParsed {
2184 CommandObjectTypeCategoryList(CommandInterpreter &interpreter)
2185 : CommandObjectParsed(interpreter, "type category list",
2186 "Provide a list of all existing categories.",
2188 CommandArgumentEntry type_arg;
2189 CommandArgumentData type_style_arg;
2191 type_style_arg.arg_type = eArgTypeName;
2192 type_style_arg.arg_repetition = eArgRepeatOptional;
2194 type_arg.push_back(type_style_arg);
2196 m_arguments.push_back(type_arg);
2199 ~CommandObjectTypeCategoryList() override = default;
2202 bool DoExecute(Args &command, CommandReturnObject &result) override {
2203 const size_t argc = command.GetArgumentCount();
2205 std::unique_ptr<RegularExpression> regex;
2208 regex.reset(new RegularExpression());
2209 const char *arg = command.GetArgumentAtIndex(0);
2210 if (!regex->Compile(llvm::StringRef::withNullAsEmpty(arg))) {
2211 result.AppendErrorWithFormat(
2212 "syntax error in category regular expression '%s'", arg);
2213 result.SetStatus(eReturnStatusFailed);
2216 } else if (argc != 0) {
2217 result.AppendErrorWithFormat("%s takes 0 or one arg.\n",
2218 m_cmd_name.c_str());
2219 result.SetStatus(eReturnStatusFailed);
2223 DataVisualization::Categories::ForEach(
2224 [®ex, &result](const lldb::TypeCategoryImplSP &category_sp) -> bool {
2227 if (regex->GetText() == category_sp->GetName()) {
2229 } else if (regex->Execute(llvm::StringRef::withNullAsEmpty(
2230 category_sp->GetName()))) {
2238 result.GetOutputStream().Printf(
2239 "Category: %s\n", category_sp->GetDescription().c_str());
2244 result.SetStatus(eReturnStatusSuccessFinishResult);
2245 return result.Succeeded();
2249 //-------------------------------------------------------------------------
2250 // CommandObjectTypeFilterList
2251 //-------------------------------------------------------------------------
2253 class CommandObjectTypeFilterList
2254 : public CommandObjectTypeFormatterList<TypeFilterImpl> {
2256 CommandObjectTypeFilterList(CommandInterpreter &interpreter)
2257 : CommandObjectTypeFormatterList(interpreter, "type filter list",
2258 "Show a list of current filters.") {}
2261 #ifndef LLDB_DISABLE_PYTHON
2263 //-------------------------------------------------------------------------
2264 // CommandObjectTypeSynthList
2265 //-------------------------------------------------------------------------
2267 class CommandObjectTypeSynthList
2268 : public CommandObjectTypeFormatterList<SyntheticChildren> {
2270 CommandObjectTypeSynthList(CommandInterpreter &interpreter)
2271 : CommandObjectTypeFormatterList(
2272 interpreter, "type synthetic list",
2273 "Show a list of current synthetic providers.") {}
2276 #endif // LLDB_DISABLE_PYTHON
2278 //-------------------------------------------------------------------------
2279 // CommandObjectTypeFilterDelete
2280 //-------------------------------------------------------------------------
2282 class CommandObjectTypeFilterDelete : public CommandObjectTypeFormatterDelete {
2284 CommandObjectTypeFilterDelete(CommandInterpreter &interpreter)
2285 : CommandObjectTypeFormatterDelete(
2287 eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter,
2288 "type filter delete", "Delete an existing filter for a type.") {}
2290 ~CommandObjectTypeFilterDelete() override = default;
2293 #ifndef LLDB_DISABLE_PYTHON
2295 //-------------------------------------------------------------------------
2296 // CommandObjectTypeSynthDelete
2297 //-------------------------------------------------------------------------
2299 class CommandObjectTypeSynthDelete : public CommandObjectTypeFormatterDelete {
2301 CommandObjectTypeSynthDelete(CommandInterpreter &interpreter)
2302 : CommandObjectTypeFormatterDelete(
2304 eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth,
2305 "type synthetic delete",
2306 "Delete an existing synthetic provider for a type.") {}
2308 ~CommandObjectTypeSynthDelete() override = default;
2311 #endif // LLDB_DISABLE_PYTHON
2313 //-------------------------------------------------------------------------
2314 // CommandObjectTypeFilterClear
2315 //-------------------------------------------------------------------------
2317 class CommandObjectTypeFilterClear : public CommandObjectTypeFormatterClear {
2319 CommandObjectTypeFilterClear(CommandInterpreter &interpreter)
2320 : CommandObjectTypeFormatterClear(
2322 eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter,
2323 "type filter clear", "Delete all existing filter.") {}
2326 #ifndef LLDB_DISABLE_PYTHON
2327 //-------------------------------------------------------------------------
2328 // CommandObjectTypeSynthClear
2329 //-------------------------------------------------------------------------
2331 class CommandObjectTypeSynthClear : public CommandObjectTypeFormatterClear {
2333 CommandObjectTypeSynthClear(CommandInterpreter &interpreter)
2334 : CommandObjectTypeFormatterClear(
2336 eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth,
2337 "type synthetic clear",
2338 "Delete all existing synthetic providers.") {}
2341 bool CommandObjectTypeSynthAdd::Execute_HandwritePython(
2342 Args &command, CommandReturnObject &result) {
2343 SynthAddOptions *options = new SynthAddOptions(
2344 m_options.m_skip_pointers, m_options.m_skip_references,
2345 m_options.m_cascade, m_options.m_regex, m_options.m_category);
2347 for (auto &entry : command.entries()) {
2348 if (entry.ref.empty()) {
2349 result.AppendError("empty typenames not allowed");
2350 result.SetStatus(eReturnStatusFailed);
2354 options->m_target_types << entry.ref;
2357 m_interpreter.GetPythonCommandsFromIOHandler(
2359 *this, // IOHandlerDelegate
2360 true, // Run IOHandler in async mode
2361 options); // Baton for the "io_handler" that will be passed back into our
2362 // IOHandlerDelegate functions
2363 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2364 return result.Succeeded();
2367 bool CommandObjectTypeSynthAdd::Execute_PythonClass(
2368 Args &command, CommandReturnObject &result) {
2369 const size_t argc = command.GetArgumentCount();
2372 result.AppendErrorWithFormat("%s takes one or more args.\n",
2373 m_cmd_name.c_str());
2374 result.SetStatus(eReturnStatusFailed);
2378 if (m_options.m_class_name.empty() && !m_options.m_input_python) {
2379 result.AppendErrorWithFormat("%s needs either a Python class name or -P to "
2380 "directly input Python code.\n",
2381 m_cmd_name.c_str());
2382 result.SetStatus(eReturnStatusFailed);
2386 SyntheticChildrenSP entry;
2388 ScriptedSyntheticChildren *impl = new ScriptedSyntheticChildren(
2389 SyntheticChildren::Flags()
2390 .SetCascades(m_options.m_cascade)
2391 .SetSkipPointers(m_options.m_skip_pointers)
2392 .SetSkipReferences(m_options.m_skip_references),
2393 m_options.m_class_name.c_str());
2397 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
2400 !interpreter->CheckObjectExists(impl->GetPythonClassName()))
2401 result.AppendWarning("The provided class does not exist - please define it "
2402 "before attempting to use this synthetic provider");
2404 // now I have a valid provider, let's add it to every type
2406 lldb::TypeCategoryImplSP category;
2407 DataVisualization::Categories::GetCategory(
2408 ConstString(m_options.m_category.c_str()), category);
2412 for (auto &arg_entry : command.entries()) {
2413 if (arg_entry.ref.empty()) {
2414 result.AppendError("empty typenames not allowed");
2415 result.SetStatus(eReturnStatusFailed);
2419 ConstString typeCS(arg_entry.ref);
2420 if (!AddSynth(typeCS, entry,
2421 m_options.m_regex ? eRegexSynth : eRegularSynth,
2422 m_options.m_category, &error)) {
2423 result.AppendError(error.AsCString());
2424 result.SetStatus(eReturnStatusFailed);
2429 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2430 return result.Succeeded();
2433 CommandObjectTypeSynthAdd::CommandObjectTypeSynthAdd(
2434 CommandInterpreter &interpreter)
2435 : CommandObjectParsed(interpreter, "type synthetic add",
2436 "Add a new synthetic provider for a type.", nullptr),
2437 IOHandlerDelegateMultiline("DONE"), m_options() {
2438 CommandArgumentEntry type_arg;
2439 CommandArgumentData type_style_arg;
2441 type_style_arg.arg_type = eArgTypeName;
2442 type_style_arg.arg_repetition = eArgRepeatPlus;
2444 type_arg.push_back(type_style_arg);
2446 m_arguments.push_back(type_arg);
2449 bool CommandObjectTypeSynthAdd::AddSynth(ConstString type_name,
2450 SyntheticChildrenSP entry,
2451 SynthFormatType type,
2452 std::string category_name,
2454 lldb::TypeCategoryImplSP category;
2455 DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()),
2458 if (type == eRegularSynth) {
2459 if (FixArrayTypeNameWithRegex(type_name))
2463 if (category->AnyMatches(type_name, eFormatCategoryItemFilter |
2464 eFormatCategoryItemRegexFilter,
2467 error->SetErrorStringWithFormat("cannot add synthetic for type %s when "
2468 "filter is defined in same category!",
2469 type_name.AsCString());
2473 if (type == eRegexSynth) {
2474 RegularExpressionSP typeRX(new RegularExpression());
2475 if (!typeRX->Compile(type_name.GetStringRef())) {
2477 error->SetErrorString(
2478 "regex format error (maybe this is not really a regex?)");
2482 category->GetRegexTypeSyntheticsContainer()->Delete(type_name);
2483 category->GetRegexTypeSyntheticsContainer()->Add(typeRX, entry);
2487 category->GetTypeSyntheticsContainer()->Add(type_name, entry);
2492 #endif // LLDB_DISABLE_PYTHON
2494 static OptionDefinition g_type_filter_add_options[] = {
2496 { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, cascade through typedef chains." },
2497 { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects." },
2498 { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for references-to-type objects." },
2499 { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Add this to the given category instead of the default one." },
2500 { LLDB_OPT_SET_ALL, false, "child", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpressionPath, "Include this expression path in the synthetic view." },
2501 { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Type names are actually regular expressions." }
2505 class CommandObjectTypeFilterAdd : public CommandObjectParsed {
2507 class CommandOptions : public Options {
2508 typedef std::vector<std::string> option_vector;
2511 CommandOptions() : Options() {}
2513 ~CommandOptions() override = default;
2515 Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2516 ExecutionContext *execution_context) override {
2518 const int short_option = m_getopt_table[option_idx].val;
2521 switch (short_option) {
2523 m_cascade = Args::StringToBoolean(option_arg, true, &success);
2525 error.SetErrorStringWithFormat("invalid value for cascade: %s",
2526 option_arg.str().c_str());
2529 m_expr_paths.push_back(option_arg);
2530 has_child_list = true;
2533 m_skip_pointers = true;
2536 m_skip_references = true;
2539 m_category = std::string(option_arg);
2545 error.SetErrorStringWithFormat("unrecognized option '%c'",
2553 void OptionParsingStarting(ExecutionContext *execution_context) override {
2555 m_skip_pointers = false;
2556 m_skip_references = false;
2557 m_category = "default";
2558 m_expr_paths.clear();
2559 has_child_list = false;
2563 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2564 return llvm::makeArrayRef(g_type_filter_add_options);
2567 // Instance variables to hold the values for command options.
2570 bool m_skip_references;
2571 bool m_skip_pointers;
2572 bool m_input_python;
2573 option_vector m_expr_paths;
2574 std::string m_category;
2575 bool has_child_list;
2578 typedef option_vector::iterator ExpressionPathsIterator;
2581 CommandOptions m_options;
2583 Options *GetOptions() override { return &m_options; }
2585 enum FilterFormatType { eRegularFilter, eRegexFilter };
2587 bool AddFilter(ConstString type_name, TypeFilterImplSP entry,
2588 FilterFormatType type, std::string category_name,
2590 lldb::TypeCategoryImplSP category;
2591 DataVisualization::Categories::GetCategory(
2592 ConstString(category_name.c_str()), category);
2594 if (type == eRegularFilter) {
2595 if (FixArrayTypeNameWithRegex(type_name))
2596 type = eRegexFilter;
2599 if (category->AnyMatches(type_name, eFormatCategoryItemSynth |
2600 eFormatCategoryItemRegexSynth,
2603 error->SetErrorStringWithFormat("cannot add filter for type %s when "
2604 "synthetic is defined in same "
2606 type_name.AsCString());
2610 if (type == eRegexFilter) {
2611 RegularExpressionSP typeRX(new RegularExpression());
2612 if (!typeRX->Compile(type_name.GetStringRef())) {
2614 error->SetErrorString(
2615 "regex format error (maybe this is not really a regex?)");
2619 category->GetRegexTypeFiltersContainer()->Delete(type_name);
2620 category->GetRegexTypeFiltersContainer()->Add(typeRX, entry);
2624 category->GetTypeFiltersContainer()->Add(type_name, entry);
2630 CommandObjectTypeFilterAdd(CommandInterpreter &interpreter)
2631 : CommandObjectParsed(interpreter, "type filter add",
2632 "Add a new filter for a type.", nullptr),
2634 CommandArgumentEntry type_arg;
2635 CommandArgumentData type_style_arg;
2637 type_style_arg.arg_type = eArgTypeName;
2638 type_style_arg.arg_repetition = eArgRepeatPlus;
2640 type_arg.push_back(type_style_arg);
2642 m_arguments.push_back(type_arg);
2646 The following examples of 'type filter add' refer to this code snippet for context:
2661 Adding a simple filter:
2663 (lldb) type filter add --child a --child g Foo
2664 (lldb) frame variable my_foo
2667 "Produces output where only a and g are displayed. Other children of my_foo \
2668 (b, c, d, e, f, h and i) are available by asking for them explicitly:"
2671 (lldb) frame variable my_foo.b my_foo.c my_foo.i
2674 "The formatting option --raw on frame variable bypasses the filter, showing \
2675 all children of my_foo as if no filter was defined:"
2678 (lldb) frame variable my_foo --raw)");
2681 ~CommandObjectTypeFilterAdd() override = default;
2684 bool DoExecute(Args &command, CommandReturnObject &result) override {
2685 const size_t argc = command.GetArgumentCount();
2688 result.AppendErrorWithFormat("%s takes one or more args.\n",
2689 m_cmd_name.c_str());
2690 result.SetStatus(eReturnStatusFailed);
2694 if (m_options.m_expr_paths.empty()) {
2695 result.AppendErrorWithFormat("%s needs one or more children.\n",
2696 m_cmd_name.c_str());
2697 result.SetStatus(eReturnStatusFailed);
2701 TypeFilterImplSP entry(new TypeFilterImpl(
2702 SyntheticChildren::Flags()
2703 .SetCascades(m_options.m_cascade)
2704 .SetSkipPointers(m_options.m_skip_pointers)
2705 .SetSkipReferences(m_options.m_skip_references)));
2707 // go through the expression paths
2708 CommandOptions::ExpressionPathsIterator begin,
2709 end = m_options.m_expr_paths.end();
2711 for (begin = m_options.m_expr_paths.begin(); begin != end; begin++)
2712 entry->AddExpressionPath(*begin);
2714 // now I have a valid provider, let's add it to every type
2716 lldb::TypeCategoryImplSP category;
2717 DataVisualization::Categories::GetCategory(
2718 ConstString(m_options.m_category.c_str()), category);
2722 WarnOnPotentialUnquotedUnsignedType(command, result);
2724 for (auto &arg_entry : command.entries()) {
2725 if (arg_entry.ref.empty()) {
2726 result.AppendError("empty typenames not allowed");
2727 result.SetStatus(eReturnStatusFailed);
2731 ConstString typeCS(arg_entry.ref);
2732 if (!AddFilter(typeCS, entry,
2733 m_options.m_regex ? eRegexFilter : eRegularFilter,
2734 m_options.m_category, &error)) {
2735 result.AppendError(error.AsCString());
2736 result.SetStatus(eReturnStatusFailed);
2741 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2742 return result.Succeeded();
2746 //----------------------------------------------------------------------
2748 //----------------------------------------------------------------------
2749 static OptionDefinition g_type_lookup_options[] = {
2751 { LLDB_OPT_SET_ALL, false, "show-help", 'h', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display available help for types" },
2752 { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Which language's types should the search scope be" }
2756 class CommandObjectTypeLookup : public CommandObjectRaw {
2758 // this function is allowed to do a more aggressive job at guessing languages
2759 // than the expression parser
2760 // is comfortable with - so leave the original call alone and add one that is
2761 // specific to type lookup
2762 lldb::LanguageType GuessLanguage(StackFrame *frame) {
2763 lldb::LanguageType lang_type = lldb::eLanguageTypeUnknown;
2768 lang_type = frame->GuessLanguage();
2769 if (lang_type != lldb::eLanguageTypeUnknown)
2772 Symbol *s = frame->GetSymbolContext(eSymbolContextSymbol).symbol;
2774 lang_type = s->GetMangled().GuessLanguage();
2779 class CommandOptions : public OptionGroup {
2782 : OptionGroup(), m_show_help(false), m_language(eLanguageTypeUnknown) {}
2784 ~CommandOptions() override = default;
2786 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2787 return llvm::makeArrayRef(g_type_lookup_options);
2790 Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
2791 ExecutionContext *execution_context) override {
2794 const int short_option = g_type_lookup_options[option_idx].short_option;
2796 switch (short_option) {
2802 m_language = Language::GetLanguageTypeFromString(option_value);
2806 error.SetErrorStringWithFormat("invalid short option character '%c'",
2814 void OptionParsingStarting(ExecutionContext *execution_context) override {
2815 m_show_help = false;
2816 m_language = eLanguageTypeUnknown;
2819 // Options table: Required for subclasses of Options.
2822 lldb::LanguageType m_language;
2825 OptionGroupOptions m_option_group;
2826 CommandOptions m_command_options;
2829 CommandObjectTypeLookup(CommandInterpreter &interpreter)
2830 : CommandObjectRaw(interpreter, "type lookup",
2831 "Lookup types and declarations in the current target, "
2832 "following language-specific naming conventions.",
2833 "type lookup <type-specifier>",
2834 eCommandRequiresTarget),
2835 m_option_group(), m_command_options() {
2836 m_option_group.Append(&m_command_options);
2837 m_option_group.Finalize();
2840 ~CommandObjectTypeLookup() override = default;
2842 Options *GetOptions() override { return &m_option_group; }
2844 llvm::StringRef GetHelpLong() override {
2845 if (!m_cmd_help_long.empty())
2846 return m_cmd_help_long;
2848 StreamString stream;
2849 // FIXME: hardcoding languages is not good
2850 lldb::LanguageType languages[] = {eLanguageTypeObjC,
2851 eLanguageTypeC_plus_plus};
2853 for (const auto lang_type : languages) {
2854 if (auto language = Language::FindPlugin(lang_type)) {
2855 if (const char *help = language->GetLanguageSpecificTypeLookupHelp()) {
2856 stream.Printf("%s\n", help);
2861 m_cmd_help_long = stream.GetString();
2862 return m_cmd_help_long;
2865 bool DoExecute(const char *raw_command_line,
2866 CommandReturnObject &result) override {
2867 if (!raw_command_line || !raw_command_line[0]) {
2869 "type lookup cannot be invoked without a type name as argument");
2873 auto exe_ctx = GetCommandInterpreter().GetExecutionContext();
2874 m_option_group.NotifyOptionParsingStarting(&exe_ctx);
2876 const char *name_of_type = nullptr;
2878 if (raw_command_line[0] == '-') {
2879 // We have some options and these options MUST end with --.
2880 const char *end_options = nullptr;
2881 const char *s = raw_command_line;
2883 end_options = ::strstr(s, "--");
2885 end_options += 2; // Get past the "--"
2886 if (::isspace(end_options[0])) {
2887 name_of_type = end_options;
2888 while (::isspace(*name_of_type))
2898 llvm::StringRef(raw_command_line, end_options - raw_command_line));
2899 if (!ParseOptions(args, result))
2902 Error error(m_option_group.NotifyOptionParsingFinished(&exe_ctx));
2904 result.AppendError(error.AsCString());
2905 result.SetStatus(eReturnStatusFailed);
2910 if (nullptr == name_of_type)
2911 name_of_type = raw_command_line;
2914 // target_sp(GetCommandInterpreter().GetDebugger().GetSelectedTarget());
2915 // const bool fill_all_in = true;
2916 // ExecutionContext exe_ctx(target_sp.get(), fill_all_in);
2917 ExecutionContextScope *best_scope = exe_ctx.GetBestExecutionContextScope();
2919 bool any_found = false;
2921 std::vector<Language *> languages;
2923 bool is_global_search = false;
2924 LanguageType guessed_language = lldb::eLanguageTypeUnknown;
2926 if ((is_global_search =
2927 (m_command_options.m_language == eLanguageTypeUnknown))) {
2928 // FIXME: hardcoding languages is not good
2929 languages.push_back(Language::FindPlugin(eLanguageTypeObjC));
2930 languages.push_back(Language::FindPlugin(eLanguageTypeC_plus_plus));
2932 languages.push_back(Language::FindPlugin(m_command_options.m_language));
2935 // This is not the most efficient way to do this, but we support very few
2937 // so the cost of the sort is going to be dwarfed by the actual lookup
2939 if (StackFrame *frame = m_exe_ctx.GetFramePtr()) {
2940 guessed_language = GuessLanguage(frame);
2941 if (guessed_language != eLanguageTypeUnknown) {
2943 languages.begin(), languages.end(),
2944 [guessed_language](Language *lang1, Language *lang2) -> bool {
2945 if (!lang1 || !lang2)
2947 LanguageType lt1 = lang1->GetLanguageType();
2948 LanguageType lt2 = lang2->GetLanguageType();
2949 if (lt1 == guessed_language)
2950 return true; // make the selected frame's language come first
2951 if (lt2 == guessed_language)
2952 return false; // make the selected frame's language come first
2953 return (lt1 < lt2); // normal comparison otherwise
2958 bool is_first_language = true;
2960 for (Language *language : languages) {
2964 if (auto scavenger = language->GetTypeScavenger()) {
2965 Language::TypeScavenger::ResultSet search_results;
2966 if (scavenger->Find(best_scope, name_of_type, search_results) > 0) {
2967 for (const auto &search_result : search_results) {
2968 if (search_result && search_result->IsValid()) {
2970 search_result->DumpToStream(result.GetOutputStream(),
2971 this->m_command_options.m_show_help);
2976 // this is "type lookup SomeName" and we did find a match, so get out
2977 if (any_found && is_global_search)
2979 else if (is_first_language && is_global_search &&
2980 guessed_language != lldb::eLanguageTypeUnknown) {
2981 is_first_language = false;
2982 result.GetOutputStream().Printf(
2983 "no type was found in the current language %s matching '%s'; "
2984 "performing a global search across all languages\n",
2985 Language::GetNameForLanguageType(guessed_language), name_of_type);
2990 result.AppendMessageWithFormat("no type was found matching '%s'\n",
2993 result.SetStatus(any_found ? lldb::eReturnStatusSuccessFinishResult
2994 : lldb::eReturnStatusSuccessFinishNoResult);
2999 template <typename FormatterType>
3000 class CommandObjectFormatterInfo : public CommandObjectRaw {
3002 typedef std::function<typename FormatterType::SharedPointer(ValueObject &)>
3004 CommandObjectFormatterInfo(CommandInterpreter &interpreter,
3005 const char *formatter_name,
3006 DiscoveryFunction discovery_func)
3007 : CommandObjectRaw(interpreter, "", "", "",
3008 eCommandRequiresFrame),
3009 m_formatter_name(formatter_name ? formatter_name : ""),
3010 m_discovery_function(discovery_func) {
3012 name.Printf("type %s info", formatter_name);
3013 SetCommandName(name.GetString());
3015 help.Printf("This command evaluates the provided expression and shows "
3016 "which %s is applied to the resulting value (if any).",
3018 SetHelp(help.GetString());
3019 StreamString syntax;
3020 syntax.Printf("type %s info <expr>", formatter_name);
3021 SetSyntax(syntax.GetString());
3024 ~CommandObjectFormatterInfo() override = default;
3027 bool DoExecute(const char *command, CommandReturnObject &result) override {
3028 TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget();
3029 Thread *thread = GetDefaultThread();
3031 result.AppendError("no default thread");
3032 result.SetStatus(lldb::eReturnStatusFailed);
3036 StackFrameSP frame_sp = thread->GetSelectedFrame();
3037 ValueObjectSP result_valobj_sp;
3038 EvaluateExpressionOptions options;
3039 lldb::ExpressionResults expr_result = target_sp->EvaluateExpression(
3040 command, frame_sp.get(), result_valobj_sp, options);
3041 if (expr_result == eExpressionCompleted && result_valobj_sp) {
3043 result_valobj_sp->GetQualifiedRepresentationIfAvailable(
3044 target_sp->GetPreferDynamicValue(),
3045 target_sp->GetEnableSyntheticValue());
3046 typename FormatterType::SharedPointer formatter_sp =
3047 m_discovery_function(*result_valobj_sp);
3049 std::string description(formatter_sp->GetDescription());
3050 result.AppendMessageWithFormat(
3051 "%s applied to (%s) %s is: %s\n", m_formatter_name.c_str(),
3052 result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>"),
3053 command, description.c_str());
3054 result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
3056 result.AppendMessageWithFormat(
3057 "no %s applies to (%s) %s\n", m_formatter_name.c_str(),
3058 result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>"),
3060 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
3064 result.AppendError("failed to evaluate expression");
3065 result.SetStatus(lldb::eReturnStatusFailed);
3071 std::string m_formatter_name;
3072 DiscoveryFunction m_discovery_function;
3075 class CommandObjectTypeFormat : public CommandObjectMultiword {
3077 CommandObjectTypeFormat(CommandInterpreter &interpreter)
3078 : CommandObjectMultiword(
3079 interpreter, "type format",
3080 "Commands for customizing value display formats.",
3081 "type format [<sub-command-options>] ") {
3083 "add", CommandObjectSP(new CommandObjectTypeFormatAdd(interpreter)));
3084 LoadSubCommand("clear", CommandObjectSP(
3085 new CommandObjectTypeFormatClear(interpreter)));
3086 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFormatDelete(
3089 "list", CommandObjectSP(new CommandObjectTypeFormatList(interpreter)));
3091 "info", CommandObjectSP(new CommandObjectFormatterInfo<TypeFormatImpl>(
3092 interpreter, "format",
3093 [](ValueObject &valobj) -> TypeFormatImpl::SharedPointer {
3094 return valobj.GetValueFormat();
3098 ~CommandObjectTypeFormat() override = default;
3101 #ifndef LLDB_DISABLE_PYTHON
3103 class CommandObjectTypeSynth : public CommandObjectMultiword {
3105 CommandObjectTypeSynth(CommandInterpreter &interpreter)
3106 : CommandObjectMultiword(
3107 interpreter, "type synthetic",
3108 "Commands for operating on synthetic type representations.",
3109 "type synthetic [<sub-command-options>] ") {
3110 LoadSubCommand("add",
3111 CommandObjectSP(new CommandObjectTypeSynthAdd(interpreter)));
3113 "clear", CommandObjectSP(new CommandObjectTypeSynthClear(interpreter)));
3114 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSynthDelete(
3117 "list", CommandObjectSP(new CommandObjectTypeSynthList(interpreter)));
3120 CommandObjectSP(new CommandObjectFormatterInfo<SyntheticChildren>(
3121 interpreter, "synthetic",
3122 [](ValueObject &valobj) -> SyntheticChildren::SharedPointer {
3123 return valobj.GetSyntheticChildren();
3127 ~CommandObjectTypeSynth() override = default;
3130 #endif // LLDB_DISABLE_PYTHON
3132 class CommandObjectTypeFilter : public CommandObjectMultiword {
3134 CommandObjectTypeFilter(CommandInterpreter &interpreter)
3135 : CommandObjectMultiword(interpreter, "type filter",
3136 "Commands for operating on type filters.",
3137 "type synthetic [<sub-command-options>] ") {
3139 "add", CommandObjectSP(new CommandObjectTypeFilterAdd(interpreter)));
3140 LoadSubCommand("clear", CommandObjectSP(
3141 new CommandObjectTypeFilterClear(interpreter)));
3142 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFilterDelete(
3145 "list", CommandObjectSP(new CommandObjectTypeFilterList(interpreter)));
3148 ~CommandObjectTypeFilter() override = default;
3151 class CommandObjectTypeCategory : public CommandObjectMultiword {
3153 CommandObjectTypeCategory(CommandInterpreter &interpreter)
3154 : CommandObjectMultiword(interpreter, "type category",
3155 "Commands for operating on type categories.",
3156 "type category [<sub-command-options>] ") {
3159 CommandObjectSP(new CommandObjectTypeCategoryDefine(interpreter)));
3162 CommandObjectSP(new CommandObjectTypeCategoryEnable(interpreter)));
3165 CommandObjectSP(new CommandObjectTypeCategoryDisable(interpreter)));
3168 CommandObjectSP(new CommandObjectTypeCategoryDelete(interpreter)));
3169 LoadSubCommand("list", CommandObjectSP(
3170 new CommandObjectTypeCategoryList(interpreter)));
3173 ~CommandObjectTypeCategory() override = default;
3176 class CommandObjectTypeSummary : public CommandObjectMultiword {
3178 CommandObjectTypeSummary(CommandInterpreter &interpreter)
3179 : CommandObjectMultiword(
3180 interpreter, "type summary",
3181 "Commands for editing variable summary display options.",
3182 "type summary [<sub-command-options>] ") {
3184 "add", CommandObjectSP(new CommandObjectTypeSummaryAdd(interpreter)));
3185 LoadSubCommand("clear", CommandObjectSP(new CommandObjectTypeSummaryClear(
3187 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSummaryDelete(
3190 "list", CommandObjectSP(new CommandObjectTypeSummaryList(interpreter)));
3192 "info", CommandObjectSP(new CommandObjectFormatterInfo<TypeSummaryImpl>(
3193 interpreter, "summary",
3194 [](ValueObject &valobj) -> TypeSummaryImpl::SharedPointer {
3195 return valobj.GetSummaryFormat();
3199 ~CommandObjectTypeSummary() override = default;
3202 //-------------------------------------------------------------------------
3203 // CommandObjectType
3204 //-------------------------------------------------------------------------
3206 CommandObjectType::CommandObjectType(CommandInterpreter &interpreter)
3207 : CommandObjectMultiword(interpreter, "type",
3208 "Commands for operating on the type system.",
3209 "type [<sub-command-options>]") {
3210 LoadSubCommand("category",
3211 CommandObjectSP(new CommandObjectTypeCategory(interpreter)));
3212 LoadSubCommand("filter",
3213 CommandObjectSP(new CommandObjectTypeFilter(interpreter)));
3214 LoadSubCommand("format",
3215 CommandObjectSP(new CommandObjectTypeFormat(interpreter)));
3216 LoadSubCommand("summary",
3217 CommandObjectSP(new CommandObjectTypeSummary(interpreter)));
3218 #ifndef LLDB_DISABLE_PYTHON
3219 LoadSubCommand("synthetic",
3220 CommandObjectSP(new CommandObjectTypeSynth(interpreter)));
3221 #endif // LLDB_DISABLE_PYTHON
3222 LoadSubCommand("lookup",
3223 CommandObjectSP(new CommandObjectTypeLookup(interpreter)));
3226 CommandObjectType::~CommandObjectType() = default;