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/Debugger.h"
20 #include "lldb/Core/IOHandler.h"
21 #include "lldb/Core/State.h"
22 #include "lldb/DataFormatters/DataVisualization.h"
23 #include "lldb/Host/OptionParser.h"
24 #include "lldb/Interpreter/CommandInterpreter.h"
25 #include "lldb/Interpreter/CommandObject.h"
26 #include "lldb/Interpreter/CommandReturnObject.h"
27 #include "lldb/Interpreter/OptionArgParser.h"
28 #include "lldb/Interpreter/OptionGroupFormat.h"
29 #include "lldb/Interpreter/OptionValueBoolean.h"
30 #include "lldb/Interpreter/OptionValueLanguage.h"
31 #include "lldb/Interpreter/OptionValueString.h"
32 #include "lldb/Interpreter/Options.h"
33 #include "lldb/Symbol/Symbol.h"
34 #include "lldb/Target/Language.h"
35 #include "lldb/Target/Process.h"
36 #include "lldb/Target/StackFrame.h"
37 #include "lldb/Target/Target.h"
38 #include "lldb/Target/Thread.h"
39 #include "lldb/Target/ThreadList.h"
40 #include "lldb/Utility/ConstString.h"
41 #include "lldb/Utility/RegularExpression.h"
42 #include "lldb/Utility/StringList.h"
44 // Other libraries and framework includes
45 #include "llvm/ADT/STLExtras.h"
48 using namespace lldb_private;
50 class ScriptAddOptions {
52 TypeSummaryImpl::Flags m_flags;
53 StringList m_target_types;
56 std::string m_category;
58 ScriptAddOptions(const TypeSummaryImpl::Flags &flags, bool regx,
59 const ConstString &name, std::string catg)
60 : m_flags(flags), m_regex(regx), m_name(name), m_category(catg) {}
62 typedef std::shared_ptr<ScriptAddOptions> SharedPointer;
65 class SynthAddOptions {
68 bool m_skip_references;
71 StringList m_target_types;
72 std::string m_category;
74 SynthAddOptions(bool sptr, bool sref, bool casc, bool regx, std::string catg)
75 : m_skip_pointers(sptr), m_skip_references(sref), m_cascade(casc),
76 m_regex(regx), m_target_types(), m_category(catg) {}
78 typedef std::shared_ptr<SynthAddOptions> SharedPointer;
81 static bool WarnOnPotentialUnquotedUnsignedType(Args &command,
82 CommandReturnObject &result) {
86 for (auto entry : llvm::enumerate(command.entries().drop_back())) {
87 if (entry.value().ref != "unsigned")
89 auto next = command.entries()[entry.index() + 1].ref;
90 if (next == "int" || next == "short" || next == "char" || next == "long") {
91 result.AppendWarningWithFormat(
92 "unsigned %s being treated as two types. if you meant the combined "
94 "name use quotes, as in \"unsigned %s\"\n",
95 next.str().c_str(), next.str().c_str());
102 static OptionDefinition g_type_summary_add_options[] = {
104 { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Add this to the given category instead of the default one." },
105 { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, cascade through typedef chains." },
106 { 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." },
107 { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects." },
108 { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for references-to-type objects." },
109 { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Type names are actually regular expressions." },
110 { LLDB_OPT_SET_1, true, "inline-children", 'c', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "If true, inline all child values into summary string." },
111 { LLDB_OPT_SET_1, false, "omit-names", 'O', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "If true, omit value names in the summary display." },
112 { LLDB_OPT_SET_2, true, "summary-string", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeSummaryString, "Summary string used to display text and object contents." },
113 { 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." },
114 { 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." },
115 { LLDB_OPT_SET_3, false, "input-python", 'P', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Input Python code to use for this type manually." },
116 { 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." },
117 { 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." },
118 { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "A name for this summary string." }
122 class CommandObjectTypeSummaryAdd : public CommandObjectParsed,
123 public IOHandlerDelegateMultiline {
125 class CommandOptions : public Options {
127 CommandOptions(CommandInterpreter &interpreter) : Options() {}
129 ~CommandOptions() override = default;
131 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
132 ExecutionContext *execution_context) override;
134 void OptionParsingStarting(ExecutionContext *execution_context) override;
136 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
137 return llvm::makeArrayRef(g_type_summary_add_options);
140 // Instance variables to hold the values for command options.
142 TypeSummaryImpl::Flags m_flags;
144 std::string m_format_string;
146 std::string m_python_script;
147 std::string m_python_function;
148 bool m_is_add_script;
149 std::string m_category;
152 CommandOptions m_options;
154 Options *GetOptions() override { return &m_options; }
156 bool Execute_ScriptSummary(Args &command, CommandReturnObject &result);
158 bool Execute_StringSummary(Args &command, CommandReturnObject &result);
161 enum SummaryFormatType { eRegularSummary, eRegexSummary, eNamedSummary };
163 CommandObjectTypeSummaryAdd(CommandInterpreter &interpreter);
165 ~CommandObjectTypeSummaryAdd() override = default;
167 void IOHandlerActivated(IOHandler &io_handler) override {
168 static const char *g_summary_addreader_instructions =
169 "Enter your Python command(s). Type 'DONE' to end.\n"
170 "def function (valobj,internal_dict):\n"
171 " \"\"\"valobj: an SBValue which you want to provide a summary "
173 " internal_dict: an LLDB support object not to be used\"\"\"\n";
175 StreamFileSP output_sp(io_handler.GetOutputStreamFile());
177 output_sp->PutCString(g_summary_addreader_instructions);
182 void IOHandlerInputComplete(IOHandler &io_handler,
183 std::string &data) override {
184 StreamFileSP error_sp = io_handler.GetErrorStreamFile();
186 #ifndef LLDB_DISABLE_PYTHON
187 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
190 lines.SplitIntoLines(data);
191 if (lines.GetSize() > 0) {
192 ScriptAddOptions *options_ptr =
193 ((ScriptAddOptions *)io_handler.GetUserData());
195 ScriptAddOptions::SharedPointer options(
196 options_ptr); // this will ensure that we get rid of the pointer
197 // when going out of scope
199 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
201 std::string funct_name_str;
202 if (interpreter->GenerateTypeScriptFunction(lines,
204 if (funct_name_str.empty()) {
205 error_sp->Printf("unable to obtain a valid function name from "
206 "the script interpreter.\n");
209 // now I have a valid function name, let's add this as script
210 // for every type in the list
212 TypeSummaryImplSP script_format;
213 script_format.reset(new ScriptSummaryFormat(
214 options->m_flags, funct_name_str.c_str(),
215 lines.CopyList(" ").c_str()));
219 for (size_t i = 0; i < options->m_target_types.GetSize(); i++) {
220 const char *type_name =
221 options->m_target_types.GetStringAtIndex(i);
222 CommandObjectTypeSummaryAdd::AddSummary(
223 ConstString(type_name), script_format,
225 ? CommandObjectTypeSummaryAdd::eRegexSummary
226 : CommandObjectTypeSummaryAdd::eRegularSummary),
227 options->m_category, &error);
229 error_sp->Printf("error: %s", error.AsCString());
234 if (options->m_name) {
235 CommandObjectTypeSummaryAdd::AddSummary(
236 options->m_name, script_format,
237 CommandObjectTypeSummaryAdd::eNamedSummary,
238 options->m_category, &error);
240 CommandObjectTypeSummaryAdd::AddSummary(
241 options->m_name, script_format,
242 CommandObjectTypeSummaryAdd::eNamedSummary,
243 options->m_category, &error);
245 error_sp->Printf("error: %s", error.AsCString());
249 error_sp->Printf("error: %s", error.AsCString());
253 if (error.AsCString()) {
254 error_sp->Printf("error: %s", error.AsCString());
260 error_sp->Printf("error: unable to generate a function.\n");
264 error_sp->Printf("error: no script interpreter.\n");
268 error_sp->Printf("error: internal synchronization information "
269 "missing or invalid.\n");
273 error_sp->Printf("error: empty function, didn't add python command.\n");
278 "error: script interpreter missing, didn't add python command.\n");
281 #endif // LLDB_DISABLE_PYTHON
282 io_handler.SetIsDone(true);
285 static bool AddSummary(ConstString type_name, lldb::TypeSummaryImplSP entry,
286 SummaryFormatType type, std::string category,
287 Status *error = nullptr);
290 bool DoExecute(Args &command, CommandReturnObject &result) override;
293 static const char *g_synth_addreader_instructions =
294 "Enter your Python command(s). Type 'DONE' to end.\n"
295 "You must define a Python class with these methods:\n"
296 " def __init__(self, valobj, dict):\n"
297 " def num_children(self):\n"
298 " def get_child_at_index(self, index):\n"
299 " def get_child_index(self, name):\n"
300 " def update(self):\n"
302 "class synthProvider:\n";
304 static OptionDefinition g_type_synth_add_options[] = {
306 { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, cascade through typedef chains." },
307 { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects." },
308 { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for references-to-type objects." },
309 { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Add this to the given category instead of the default one." },
310 { LLDB_OPT_SET_2, false, "python-class", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonClass, "Use this Python class to produce synthetic children." },
311 { 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." },
312 { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Type names are actually regular expressions." }
316 class CommandObjectTypeSynthAdd : public CommandObjectParsed,
317 public IOHandlerDelegateMultiline {
319 class CommandOptions : public Options {
321 CommandOptions() : Options() {}
323 ~CommandOptions() override = default;
325 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
326 ExecutionContext *execution_context) override {
328 const int short_option = m_getopt_table[option_idx].val;
331 switch (short_option) {
333 m_cascade = OptionArgParser::ToBoolean(option_arg, true, &success);
335 error.SetErrorStringWithFormat("invalid value for cascade: %s",
336 option_arg.str().c_str());
339 handwrite_python = true;
342 m_class_name = std::string(option_arg);
343 is_class_based = true;
346 m_skip_pointers = true;
349 m_skip_references = true;
352 m_category = std::string(option_arg);
358 error.SetErrorStringWithFormat("unrecognized option '%c'",
366 void OptionParsingStarting(ExecutionContext *execution_context) override {
369 m_skip_pointers = false;
370 m_skip_references = false;
371 m_category = "default";
372 is_class_based = false;
373 handwrite_python = false;
377 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
378 return llvm::makeArrayRef(g_type_synth_add_options);
381 // Instance variables to hold the values for command options.
384 bool m_skip_references;
385 bool m_skip_pointers;
386 std::string m_class_name;
388 std::string m_category;
390 bool handwrite_python;
394 CommandOptions m_options;
396 Options *GetOptions() override { return &m_options; }
398 bool Execute_HandwritePython(Args &command, CommandReturnObject &result);
400 bool Execute_PythonClass(Args &command, CommandReturnObject &result);
403 bool DoExecute(Args &command, CommandReturnObject &result) override {
404 WarnOnPotentialUnquotedUnsignedType(command, result);
406 if (m_options.handwrite_python)
407 return Execute_HandwritePython(command, result);
408 else if (m_options.is_class_based)
409 return Execute_PythonClass(command, result);
411 result.AppendError("must either provide a children list, a Python class "
412 "name, or use -P and type a Python class "
414 result.SetStatus(eReturnStatusFailed);
419 void IOHandlerActivated(IOHandler &io_handler) override {
420 StreamFileSP output_sp(io_handler.GetOutputStreamFile());
422 output_sp->PutCString(g_synth_addreader_instructions);
427 void IOHandlerInputComplete(IOHandler &io_handler,
428 std::string &data) override {
429 StreamFileSP error_sp = io_handler.GetErrorStreamFile();
431 #ifndef LLDB_DISABLE_PYTHON
432 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
435 lines.SplitIntoLines(data);
436 if (lines.GetSize() > 0) {
437 SynthAddOptions *options_ptr =
438 ((SynthAddOptions *)io_handler.GetUserData());
440 SynthAddOptions::SharedPointer options(
441 options_ptr); // this will ensure that we get rid of the pointer
442 // when going out of scope
444 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
446 std::string class_name_str;
447 if (interpreter->GenerateTypeSynthClass(lines, class_name_str)) {
448 if (class_name_str.empty()) {
450 "error: unable to obtain a proper name for the class.\n");
453 // everything should be fine now, let's add the synth provider
456 SyntheticChildrenSP synth_provider;
457 synth_provider.reset(new ScriptedSyntheticChildren(
458 SyntheticChildren::Flags()
459 .SetCascades(options->m_cascade)
460 .SetSkipPointers(options->m_skip_pointers)
461 .SetSkipReferences(options->m_skip_references),
462 class_name_str.c_str()));
464 lldb::TypeCategoryImplSP category;
465 DataVisualization::Categories::GetCategory(
466 ConstString(options->m_category.c_str()), category);
470 for (size_t i = 0; i < options->m_target_types.GetSize(); i++) {
471 const char *type_name =
472 options->m_target_types.GetStringAtIndex(i);
473 ConstString const_type_name(type_name);
474 if (const_type_name) {
475 if (!CommandObjectTypeSynthAdd::AddSynth(
476 const_type_name, synth_provider,
478 ? CommandObjectTypeSynthAdd::eRegexSynth
479 : CommandObjectTypeSynthAdd::eRegularSynth,
480 options->m_category, &error)) {
481 error_sp->Printf("error: %s\n", error.AsCString());
486 error_sp->Printf("error: invalid type name.\n");
493 error_sp->Printf("error: unable to generate a class.\n");
497 error_sp->Printf("error: no script interpreter.\n");
501 error_sp->Printf("error: internal synchronization data missing.\n");
505 error_sp->Printf("error: empty function, didn't add python command.\n");
510 "error: script interpreter missing, didn't add python command.\n");
514 #endif // LLDB_DISABLE_PYTHON
515 io_handler.SetIsDone(true);
519 enum SynthFormatType { eRegularSynth, eRegexSynth };
521 CommandObjectTypeSynthAdd(CommandInterpreter &interpreter);
523 ~CommandObjectTypeSynthAdd() override = default;
525 static bool AddSynth(ConstString type_name, lldb::SyntheticChildrenSP entry,
526 SynthFormatType type, std::string category_name,
530 //-------------------------------------------------------------------------
531 // CommandObjectTypeFormatAdd
532 //-------------------------------------------------------------------------
534 static OptionDefinition g_type_format_add_options[] = {
536 { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Add this to the given category instead of the default one." },
537 { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, cascade through typedef chains." },
538 { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects." },
539 { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for references-to-type objects." },
540 { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Type names are actually regular expressions." },
541 { LLDB_OPT_SET_2, false, "type", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Format variables as if they were of this type." }
545 class CommandObjectTypeFormatAdd : public CommandObjectParsed {
547 class CommandOptions : public OptionGroup {
549 CommandOptions() : OptionGroup() {}
551 ~CommandOptions() override = default;
553 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
554 return llvm::makeArrayRef(g_type_format_add_options);
557 void OptionParsingStarting(ExecutionContext *execution_context) override {
559 m_skip_pointers = false;
560 m_skip_references = false;
562 m_category.assign("default");
563 m_custom_type_name.clear();
566 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
567 ExecutionContext *execution_context) override {
569 const int short_option =
570 g_type_format_add_options[option_idx].short_option;
573 switch (short_option) {
575 m_cascade = OptionArgParser::ToBoolean(option_value, true, &success);
577 error.SetErrorStringWithFormat("invalid value for cascade: %s",
578 option_value.str().c_str());
581 m_skip_pointers = true;
584 m_category.assign(option_value);
587 m_skip_references = true;
593 m_custom_type_name.assign(option_value);
596 error.SetErrorStringWithFormat("unrecognized option '%c'",
604 // Instance variables to hold the values for command options.
607 bool m_skip_references;
608 bool m_skip_pointers;
610 std::string m_category;
611 std::string m_custom_type_name;
614 OptionGroupOptions m_option_group;
615 OptionGroupFormat m_format_options;
616 CommandOptions m_command_options;
618 Options *GetOptions() override { return &m_option_group; }
621 CommandObjectTypeFormatAdd(CommandInterpreter &interpreter)
622 : CommandObjectParsed(interpreter, "type format add",
623 "Add a new formatting style for a type.", nullptr),
624 m_option_group(), m_format_options(eFormatInvalid),
625 m_command_options() {
626 CommandArgumentEntry type_arg;
627 CommandArgumentData type_style_arg;
629 type_style_arg.arg_type = eArgTypeName;
630 type_style_arg.arg_repetition = eArgRepeatPlus;
632 type_arg.push_back(type_style_arg);
634 m_arguments.push_back(type_arg);
638 The following examples of 'type format add' refer to this code snippet for context:
641 typedef float Afloat;
643 typedef Afloat Bfloat;
651 Adding default formatting:
653 (lldb) type format add -f hex AInt
654 (lldb) frame variable iy
657 " Produces hexadecimal display of iy, because no formatter is available for Bint and \
658 the one for Aint is used instead."
661 To prevent this use the cascade option '-C no' to prevent evaluation of typedef chains:
664 (lldb) type format add -f hex -C no AInt
666 Similar reasoning applies to this:
668 (lldb) type format add -f hex -C no float -p
671 " All float values and float references are now formatted as hexadecimal, but not \
672 pointers to floats. Nor will it change the default display for Afloat and Bfloat objects.");
674 // Add the "--format" to all options groups
675 m_option_group.Append(&m_format_options,
676 OptionGroupFormat::OPTION_GROUP_FORMAT,
678 m_option_group.Append(&m_command_options);
679 m_option_group.Finalize();
682 ~CommandObjectTypeFormatAdd() override = default;
685 bool DoExecute(Args &command, CommandReturnObject &result) override {
686 const size_t argc = command.GetArgumentCount();
689 result.AppendErrorWithFormat("%s takes one or more args.\n",
691 result.SetStatus(eReturnStatusFailed);
695 const Format format = m_format_options.GetFormat();
696 if (format == eFormatInvalid &&
697 m_command_options.m_custom_type_name.empty()) {
698 result.AppendErrorWithFormat("%s needs a valid format.\n",
700 result.SetStatus(eReturnStatusFailed);
704 TypeFormatImplSP entry;
706 if (m_command_options.m_custom_type_name.empty())
707 entry.reset(new TypeFormatImpl_Format(
708 format, TypeFormatImpl::Flags()
709 .SetCascades(m_command_options.m_cascade)
710 .SetSkipPointers(m_command_options.m_skip_pointers)
711 .SetSkipReferences(m_command_options.m_skip_references)));
713 entry.reset(new TypeFormatImpl_EnumType(
714 ConstString(m_command_options.m_custom_type_name.c_str()),
715 TypeFormatImpl::Flags()
716 .SetCascades(m_command_options.m_cascade)
717 .SetSkipPointers(m_command_options.m_skip_pointers)
718 .SetSkipReferences(m_command_options.m_skip_references)));
720 // now I have a valid format, let's add it to every type
722 TypeCategoryImplSP category_sp;
723 DataVisualization::Categories::GetCategory(
724 ConstString(m_command_options.m_category), category_sp);
728 WarnOnPotentialUnquotedUnsignedType(command, result);
730 for (auto &arg_entry : command.entries()) {
731 if (arg_entry.ref.empty()) {
732 result.AppendError("empty typenames not allowed");
733 result.SetStatus(eReturnStatusFailed);
737 ConstString typeCS(arg_entry.ref);
738 if (m_command_options.m_regex) {
739 RegularExpressionSP typeRX(new RegularExpression());
740 if (!typeRX->Compile(arg_entry.ref)) {
742 "regex format error (maybe this is not really a regex?)");
743 result.SetStatus(eReturnStatusFailed);
746 category_sp->GetRegexTypeSummariesContainer()->Delete(typeCS);
747 category_sp->GetRegexTypeFormatsContainer()->Add(typeRX, entry);
749 category_sp->GetTypeFormatsContainer()->Add(typeCS, entry);
752 result.SetStatus(eReturnStatusSuccessFinishNoResult);
753 return result.Succeeded();
757 static OptionDefinition g_type_formatter_delete_options[] = {
759 { LLDB_OPT_SET_1, false, "all", 'a', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Delete from every category." },
760 { LLDB_OPT_SET_2, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Delete from given category." },
761 { LLDB_OPT_SET_3, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Delete from given language's category." }
765 class CommandObjectTypeFormatterDelete : public CommandObjectParsed {
767 class CommandOptions : public Options {
769 CommandOptions() : Options() {}
771 ~CommandOptions() override = default;
773 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
774 ExecutionContext *execution_context) override {
776 const int short_option = m_getopt_table[option_idx].val;
778 switch (short_option) {
783 m_category = std::string(option_arg);
786 m_language = Language::GetLanguageTypeFromString(option_arg);
789 error.SetErrorStringWithFormat("unrecognized option '%c'",
797 void OptionParsingStarting(ExecutionContext *execution_context) override {
798 m_delete_all = false;
799 m_category = "default";
800 m_language = lldb::eLanguageTypeUnknown;
803 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
804 return llvm::makeArrayRef(g_type_formatter_delete_options);
807 // Instance variables to hold the values for command options.
810 std::string m_category;
811 lldb::LanguageType m_language;
814 CommandOptions m_options;
815 uint32_t m_formatter_kind_mask;
817 Options *GetOptions() override { return &m_options; }
820 CommandObjectTypeFormatterDelete(CommandInterpreter &interpreter,
821 uint32_t formatter_kind_mask,
822 const char *name, const char *help)
823 : CommandObjectParsed(interpreter, name, help, nullptr), m_options(),
824 m_formatter_kind_mask(formatter_kind_mask) {
825 CommandArgumentEntry type_arg;
826 CommandArgumentData type_style_arg;
828 type_style_arg.arg_type = eArgTypeName;
829 type_style_arg.arg_repetition = eArgRepeatPlain;
831 type_arg.push_back(type_style_arg);
833 m_arguments.push_back(type_arg);
836 ~CommandObjectTypeFormatterDelete() override = default;
839 virtual bool FormatterSpecificDeletion(ConstString typeCS) { return false; }
841 bool DoExecute(Args &command, CommandReturnObject &result) override {
842 const size_t argc = command.GetArgumentCount();
845 result.AppendErrorWithFormat("%s takes 1 arg.\n", m_cmd_name.c_str());
846 result.SetStatus(eReturnStatusFailed);
850 const char *typeA = command.GetArgumentAtIndex(0);
851 ConstString typeCS(typeA);
854 result.AppendError("empty typenames not allowed");
855 result.SetStatus(eReturnStatusFailed);
859 if (m_options.m_delete_all) {
860 DataVisualization::Categories::ForEach(
861 [this, typeCS](const lldb::TypeCategoryImplSP &category_sp) -> bool {
862 category_sp->Delete(typeCS, m_formatter_kind_mask);
865 result.SetStatus(eReturnStatusSuccessFinishNoResult);
866 return result.Succeeded();
869 bool delete_category = false;
870 bool extra_deletion = false;
872 if (m_options.m_language != lldb::eLanguageTypeUnknown) {
873 lldb::TypeCategoryImplSP category;
874 DataVisualization::Categories::GetCategory(m_options.m_language,
877 delete_category = category->Delete(typeCS, m_formatter_kind_mask);
878 extra_deletion = FormatterSpecificDeletion(typeCS);
880 lldb::TypeCategoryImplSP category;
881 DataVisualization::Categories::GetCategory(
882 ConstString(m_options.m_category.c_str()), category);
884 delete_category = category->Delete(typeCS, m_formatter_kind_mask);
885 extra_deletion = FormatterSpecificDeletion(typeCS);
888 if (delete_category || extra_deletion) {
889 result.SetStatus(eReturnStatusSuccessFinishNoResult);
890 return result.Succeeded();
892 result.AppendErrorWithFormat("no custom formatter for %s.\n", typeA);
893 result.SetStatus(eReturnStatusFailed);
899 static OptionDefinition g_type_formatter_clear_options[] = {
901 { LLDB_OPT_SET_ALL, false, "all", 'a', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Clear every category." }
905 class CommandObjectTypeFormatterClear : public CommandObjectParsed {
907 class CommandOptions : public Options {
909 CommandOptions() : Options() {}
911 ~CommandOptions() override = default;
913 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
914 ExecutionContext *execution_context) override {
916 const int short_option = m_getopt_table[option_idx].val;
918 switch (short_option) {
923 error.SetErrorStringWithFormat("unrecognized option '%c'",
931 void OptionParsingStarting(ExecutionContext *execution_context) override {
932 m_delete_all = false;
935 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
936 return llvm::makeArrayRef(g_type_formatter_clear_options);
939 // Instance variables to hold the values for command options.
943 CommandOptions m_options;
944 uint32_t m_formatter_kind_mask;
946 Options *GetOptions() override { return &m_options; }
949 CommandObjectTypeFormatterClear(CommandInterpreter &interpreter,
950 uint32_t formatter_kind_mask,
951 const char *name, const char *help)
952 : CommandObjectParsed(interpreter, name, help, nullptr), m_options(),
953 m_formatter_kind_mask(formatter_kind_mask) {}
955 ~CommandObjectTypeFormatterClear() override = default;
958 virtual void FormatterSpecificDeletion() {}
960 bool DoExecute(Args &command, CommandReturnObject &result) override {
961 if (m_options.m_delete_all) {
962 DataVisualization::Categories::ForEach(
963 [this](const TypeCategoryImplSP &category_sp) -> bool {
964 category_sp->Clear(m_formatter_kind_mask);
968 lldb::TypeCategoryImplSP category;
969 if (command.GetArgumentCount() > 0) {
970 const char *cat_name = command.GetArgumentAtIndex(0);
971 ConstString cat_nameCS(cat_name);
972 DataVisualization::Categories::GetCategory(cat_nameCS, category);
974 DataVisualization::Categories::GetCategory(ConstString(nullptr),
977 category->Clear(m_formatter_kind_mask);
980 FormatterSpecificDeletion();
982 result.SetStatus(eReturnStatusSuccessFinishResult);
983 return result.Succeeded();
987 //-------------------------------------------------------------------------
988 // CommandObjectTypeFormatDelete
989 //-------------------------------------------------------------------------
991 class CommandObjectTypeFormatDelete : public CommandObjectTypeFormatterDelete {
993 CommandObjectTypeFormatDelete(CommandInterpreter &interpreter)
994 : CommandObjectTypeFormatterDelete(
996 eFormatCategoryItemValue | eFormatCategoryItemRegexValue,
997 "type format delete",
998 "Delete an existing formatting style for a type.") {}
1000 ~CommandObjectTypeFormatDelete() override = default;
1003 //-------------------------------------------------------------------------
1004 // CommandObjectTypeFormatClear
1005 //-------------------------------------------------------------------------
1007 class CommandObjectTypeFormatClear : public CommandObjectTypeFormatterClear {
1009 CommandObjectTypeFormatClear(CommandInterpreter &interpreter)
1010 : CommandObjectTypeFormatterClear(
1012 eFormatCategoryItemValue | eFormatCategoryItemRegexValue,
1013 "type format clear", "Delete all existing format styles.") {}
1016 template <typename FormatterType>
1017 class CommandObjectTypeFormatterList : public CommandObjectParsed {
1018 typedef typename FormatterType::SharedPointer FormatterSharedPointer;
1020 class CommandOptions : public Options {
1023 : Options(), m_category_regex("", ""),
1024 m_category_language(lldb::eLanguageTypeUnknown,
1025 lldb::eLanguageTypeUnknown) {}
1027 ~CommandOptions() override = default;
1029 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1030 ExecutionContext *execution_context) override {
1032 const int short_option = m_getopt_table[option_idx].val;
1033 switch (short_option) {
1035 m_category_regex.SetCurrentValue(option_arg);
1036 m_category_regex.SetOptionWasSet();
1039 error = m_category_language.SetValueFromString(option_arg);
1040 if (error.Success())
1041 m_category_language.SetOptionWasSet();
1044 error.SetErrorStringWithFormat("unrecognized option '%c'",
1052 void OptionParsingStarting(ExecutionContext *execution_context) override {
1053 m_category_regex.Clear();
1054 m_category_language.Clear();
1057 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1058 static OptionDefinition g_option_table[] = {
1060 {LLDB_OPT_SET_1, false, "category-regex", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Only show categories matching this filter."},
1061 {LLDB_OPT_SET_2, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Only show the category for a specific language."}
1064 return llvm::ArrayRef<OptionDefinition>(g_option_table);
1067 // Instance variables to hold the values for command options.
1069 OptionValueString m_category_regex;
1070 OptionValueLanguage m_category_language;
1073 CommandOptions m_options;
1075 Options *GetOptions() override { return &m_options; }
1078 CommandObjectTypeFormatterList(CommandInterpreter &interpreter,
1079 const char *name, const char *help)
1080 : CommandObjectParsed(interpreter, name, help, nullptr), m_options() {
1081 CommandArgumentEntry type_arg;
1082 CommandArgumentData type_style_arg;
1084 type_style_arg.arg_type = eArgTypeName;
1085 type_style_arg.arg_repetition = eArgRepeatOptional;
1087 type_arg.push_back(type_style_arg);
1089 m_arguments.push_back(type_arg);
1092 ~CommandObjectTypeFormatterList() override = default;
1095 virtual bool FormatterSpecificList(CommandReturnObject &result) {
1099 bool DoExecute(Args &command, CommandReturnObject &result) override {
1100 const size_t argc = command.GetArgumentCount();
1102 std::unique_ptr<RegularExpression> category_regex;
1103 std::unique_ptr<RegularExpression> formatter_regex;
1105 if (m_options.m_category_regex.OptionWasSet()) {
1106 category_regex.reset(new RegularExpression());
1107 if (!category_regex->Compile(
1108 m_options.m_category_regex.GetCurrentValueAsRef())) {
1109 result.AppendErrorWithFormat(
1110 "syntax error in category regular expression '%s'",
1111 m_options.m_category_regex.GetCurrentValueAsRef().str().c_str());
1112 result.SetStatus(eReturnStatusFailed);
1118 const char *arg = command.GetArgumentAtIndex(0);
1119 formatter_regex.reset(new RegularExpression());
1120 if (!formatter_regex->Compile(llvm::StringRef::withNullAsEmpty(arg))) {
1121 result.AppendErrorWithFormat("syntax error in regular expression '%s'",
1123 result.SetStatus(eReturnStatusFailed);
1128 bool any_printed = false;
1130 auto category_closure = [&result, &formatter_regex, &any_printed](
1131 const lldb::TypeCategoryImplSP &category) -> void {
1132 result.GetOutputStream().Printf(
1133 "-----------------------\nCategory: %s%s\n-----------------------\n",
1134 category->GetName(), category->IsEnabled() ? "" : " (disabled)");
1136 TypeCategoryImpl::ForEachCallbacks<FormatterType> foreach;
1138 .SetExact([&result, &formatter_regex, &any_printed](
1140 const FormatterSharedPointer &format_sp) -> bool {
1141 if (formatter_regex) {
1143 if (name.GetStringRef() == formatter_regex->GetText()) {
1145 } else if (formatter_regex->Execute(name.GetStringRef())) {
1154 result.GetOutputStream().Printf("%s: %s\n", name.AsCString(),
1155 format_sp->GetDescription().c_str());
1160 .SetWithRegex([&result, &formatter_regex, &any_printed](
1161 RegularExpressionSP regex_sp,
1162 const FormatterSharedPointer &format_sp) -> bool {
1163 if (formatter_regex) {
1165 if (regex_sp->GetText() == formatter_regex->GetText()) {
1167 } else if (formatter_regex->Execute(regex_sp->GetText())) {
1176 result.GetOutputStream().Printf("%s: %s\n",
1177 regex_sp->GetText().str().c_str(),
1178 format_sp->GetDescription().c_str());
1182 category->ForEach(foreach);
1185 if (m_options.m_category_language.OptionWasSet()) {
1186 lldb::TypeCategoryImplSP category_sp;
1187 DataVisualization::Categories::GetCategory(
1188 m_options.m_category_language.GetCurrentValue(), category_sp);
1190 category_closure(category_sp);
1192 DataVisualization::Categories::ForEach(
1193 [&category_regex, &category_closure](
1194 const lldb::TypeCategoryImplSP &category) -> bool {
1195 if (category_regex) {
1197 if (category->GetName() == category_regex->GetText()) {
1199 } else if (category_regex->Execute(
1200 llvm::StringRef::withNullAsEmpty(
1201 category->GetName()))) {
1209 category_closure(category);
1214 any_printed = FormatterSpecificList(result) | any_printed;
1218 result.SetStatus(eReturnStatusSuccessFinishResult);
1220 result.GetOutputStream().PutCString("no matching results found.\n");
1221 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1223 return result.Succeeded();
1227 //-------------------------------------------------------------------------
1228 // CommandObjectTypeFormatList
1229 //-------------------------------------------------------------------------
1231 class CommandObjectTypeFormatList
1232 : public CommandObjectTypeFormatterList<TypeFormatImpl> {
1234 CommandObjectTypeFormatList(CommandInterpreter &interpreter)
1235 : CommandObjectTypeFormatterList(interpreter, "type format list",
1236 "Show a list of current formats.") {}
1239 #ifndef LLDB_DISABLE_PYTHON
1241 //-------------------------------------------------------------------------
1242 // CommandObjectTypeSummaryAdd
1243 //-------------------------------------------------------------------------
1245 #endif // LLDB_DISABLE_PYTHON
1247 Status CommandObjectTypeSummaryAdd::CommandOptions::SetOptionValue(
1248 uint32_t option_idx, llvm::StringRef option_arg,
1249 ExecutionContext *execution_context) {
1251 const int short_option = m_getopt_table[option_idx].val;
1254 switch (short_option) {
1256 m_flags.SetCascades(OptionArgParser::ToBoolean(option_arg, true, &success));
1258 error.SetErrorStringWithFormat("invalid value for cascade: %s",
1259 option_arg.str().c_str());
1262 m_flags.SetDontShowChildren(false);
1265 m_flags.SetHideEmptyAggregates(true);
1268 m_flags.SetDontShowValue(true);
1271 m_flags.SetShowMembersOneLiner(true);
1274 m_format_string = std::string(option_arg);
1277 m_flags.SetSkipPointers(true);
1280 m_flags.SetSkipReferences(true);
1286 m_name.SetString(option_arg);
1289 m_python_script = option_arg;
1290 m_is_add_script = true;
1293 m_python_function = option_arg;
1294 m_is_add_script = true;
1297 m_is_add_script = true;
1300 m_category = std::string(option_arg);
1303 m_flags.SetHideItemNames(true);
1306 error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
1313 void CommandObjectTypeSummaryAdd::CommandOptions::OptionParsingStarting(
1314 ExecutionContext *execution_context) {
1315 m_flags.Clear().SetCascades().SetDontShowChildren().SetDontShowValue(false);
1316 m_flags.SetShowMembersOneLiner(false)
1317 .SetSkipPointers(false)
1318 .SetSkipReferences(false)
1319 .SetHideItemNames(false);
1323 m_python_script = "";
1324 m_python_function = "";
1325 m_format_string = "";
1326 m_is_add_script = false;
1327 m_category = "default";
1330 #ifndef LLDB_DISABLE_PYTHON
1332 bool CommandObjectTypeSummaryAdd::Execute_ScriptSummary(
1333 Args &command, CommandReturnObject &result) {
1334 const size_t argc = command.GetArgumentCount();
1336 if (argc < 1 && !m_options.m_name) {
1337 result.AppendErrorWithFormat("%s takes one or more args.\n",
1338 m_cmd_name.c_str());
1339 result.SetStatus(eReturnStatusFailed);
1343 TypeSummaryImplSP script_format;
1345 if (!m_options.m_python_function
1346 .empty()) // we have a Python function ready to use
1348 const char *funct_name = m_options.m_python_function.c_str();
1349 if (!funct_name || !funct_name[0]) {
1350 result.AppendError("function name empty.\n");
1351 result.SetStatus(eReturnStatusFailed);
1356 (" " + m_options.m_python_function + "(valobj,internal_dict)");
1358 script_format.reset(
1359 new ScriptSummaryFormat(m_options.m_flags, funct_name, code.c_str()));
1361 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
1363 if (interpreter && !interpreter->CheckObjectExists(funct_name))
1364 result.AppendWarningWithFormat(
1365 "The provided function \"%s\" does not exist - "
1366 "please define it before attempting to use this summary.\n",
1368 } else if (!m_options.m_python_script
1369 .empty()) // we have a quick 1-line script, just use it
1371 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
1373 result.AppendError("script interpreter missing - unable to generate "
1374 "function wrapper.\n");
1375 result.SetStatus(eReturnStatusFailed);
1378 StringList funct_sl;
1379 funct_sl << m_options.m_python_script.c_str();
1380 std::string funct_name_str;
1381 if (!interpreter->GenerateTypeScriptFunction(funct_sl, funct_name_str)) {
1382 result.AppendError("unable to generate function wrapper.\n");
1383 result.SetStatus(eReturnStatusFailed);
1386 if (funct_name_str.empty()) {
1388 "script interpreter failed to generate a valid function name.\n");
1389 result.SetStatus(eReturnStatusFailed);
1393 std::string code = " " + m_options.m_python_script;
1395 script_format.reset(new ScriptSummaryFormat(
1396 m_options.m_flags, funct_name_str.c_str(), code.c_str()));
1398 // Use an IOHandler to grab Python code from the user
1399 ScriptAddOptions *options =
1400 new ScriptAddOptions(m_options.m_flags, m_options.m_regex,
1401 m_options.m_name, m_options.m_category);
1403 for (auto &entry : command.entries()) {
1404 if (entry.ref.empty()) {
1405 result.AppendError("empty typenames not allowed");
1406 result.SetStatus(eReturnStatusFailed);
1410 options->m_target_types << entry.ref;
1413 m_interpreter.GetPythonCommandsFromIOHandler(
1415 *this, // IOHandlerDelegate
1416 true, // Run IOHandler in async mode
1417 options); // Baton for the "io_handler" that will be passed back into
1418 // our IOHandlerDelegate functions
1419 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1421 return result.Succeeded();
1424 // if I am here, script_format must point to something good, so I can add
1425 // that as a script summary to all interested parties
1429 for (auto &entry : command.entries()) {
1430 CommandObjectTypeSummaryAdd::AddSummary(
1431 ConstString(entry.ref), script_format,
1432 (m_options.m_regex ? eRegexSummary : eRegularSummary),
1433 m_options.m_category, &error);
1435 result.AppendError(error.AsCString());
1436 result.SetStatus(eReturnStatusFailed);
1441 if (m_options.m_name) {
1442 AddSummary(m_options.m_name, script_format, eNamedSummary,
1443 m_options.m_category, &error);
1445 result.AppendError(error.AsCString());
1446 result.AppendError("added to types, but not given a name");
1447 result.SetStatus(eReturnStatusFailed);
1452 return result.Succeeded();
1455 #endif // LLDB_DISABLE_PYTHON
1457 bool CommandObjectTypeSummaryAdd::Execute_StringSummary(
1458 Args &command, CommandReturnObject &result) {
1459 const size_t argc = command.GetArgumentCount();
1461 if (argc < 1 && !m_options.m_name) {
1462 result.AppendErrorWithFormat("%s takes one or more args.\n",
1463 m_cmd_name.c_str());
1464 result.SetStatus(eReturnStatusFailed);
1468 if (!m_options.m_flags.GetShowMembersOneLiner() &&
1469 m_options.m_format_string.empty()) {
1470 result.AppendError("empty summary strings not allowed");
1471 result.SetStatus(eReturnStatusFailed);
1475 const char *format_cstr = (m_options.m_flags.GetShowMembersOneLiner()
1477 : m_options.m_format_string.c_str());
1479 // ${var%S} is an endless recursion, prevent it
1480 if (strcmp(format_cstr, "${var%S}") == 0) {
1481 result.AppendError("recursive summary not allowed");
1482 result.SetStatus(eReturnStatusFailed);
1486 std::unique_ptr<StringSummaryFormat> string_format(
1487 new StringSummaryFormat(m_options.m_flags, format_cstr));
1488 if (!string_format) {
1489 result.AppendError("summary creation failed");
1490 result.SetStatus(eReturnStatusFailed);
1493 if (string_format->m_error.Fail()) {
1494 result.AppendErrorWithFormat("syntax error: %s",
1495 string_format->m_error.AsCString("<unknown>"));
1496 result.SetStatus(eReturnStatusFailed);
1499 lldb::TypeSummaryImplSP entry(string_format.release());
1501 // now I have a valid format, let's add it to every type
1503 for (auto &arg_entry : command.entries()) {
1504 if (arg_entry.ref.empty()) {
1505 result.AppendError("empty typenames not allowed");
1506 result.SetStatus(eReturnStatusFailed);
1509 ConstString typeCS(arg_entry.ref);
1511 AddSummary(typeCS, entry,
1512 (m_options.m_regex ? eRegexSummary : eRegularSummary),
1513 m_options.m_category, &error);
1516 result.AppendError(error.AsCString());
1517 result.SetStatus(eReturnStatusFailed);
1522 if (m_options.m_name) {
1523 AddSummary(m_options.m_name, entry, eNamedSummary, m_options.m_category,
1526 result.AppendError(error.AsCString());
1527 result.AppendError("added to types, but not given a name");
1528 result.SetStatus(eReturnStatusFailed);
1533 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1534 return result.Succeeded();
1537 CommandObjectTypeSummaryAdd::CommandObjectTypeSummaryAdd(
1538 CommandInterpreter &interpreter)
1539 : CommandObjectParsed(interpreter, "type summary add",
1540 "Add a new summary style for a type.", nullptr),
1541 IOHandlerDelegateMultiline("DONE"), m_options(interpreter) {
1542 CommandArgumentEntry type_arg;
1543 CommandArgumentData type_style_arg;
1545 type_style_arg.arg_type = eArgTypeName;
1546 type_style_arg.arg_repetition = eArgRepeatPlus;
1548 type_arg.push_back(type_style_arg);
1550 m_arguments.push_back(type_arg);
1554 The following examples of 'type summary add' refer to this code snippet for context:
1560 JustADemo(int p = 1, float v = 0.1) : ptr(new int(p)), value(v) {}
1562 JustADemo demo_instance(42, 3.14);
1564 typedef JustADemo NewDemo;
1565 NewDemo new_demo_instance(42, 3.14);
1567 (lldb) type summary add --summary-string "the answer is ${*var.ptr}" JustADemo
1569 Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42"
1571 (lldb) type summary add --summary-string "the answer is ${*var.ptr}, and the question is ${var.value}" JustADemo
1573 Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42 and the question is 3.14"
1576 "Alternatively, you could define formatting for all pointers to integers and \
1577 rely on that when formatting JustADemo to obtain the same result:"
1580 (lldb) type summary add --summary-string "${var%V} -> ${*var}" "int *"
1581 (lldb) type summary add --summary-string "the answer is ${var.ptr}, and the question is ${var.value}" JustADemo
1584 "Type summaries are automatically applied to derived typedefs, so the examples \
1585 above apply to both JustADemo and NewDemo. The cascade option can be used to \
1586 suppress this behavior:"
1589 (lldb) type summary add --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo -C no
1591 The summary will now be used for values of JustADemo but not NewDemo.
1594 "By default summaries are shown for pointers and references to values of the \
1595 specified type. To suppress formatting for pointers use the -p option, or apply \
1596 the corresponding -r option to suppress formatting for references:"
1599 (lldb) type summary add -p -r --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo
1602 "One-line summaries including all fields in a type can be inferred without supplying an \
1603 explicit summary string by passing the -c option:"
1606 (lldb) type summary add -c JustADemo
1607 (lldb) frame variable demo_instance
1608 (ptr=<address>, value=3.14)
1611 "Type summaries normally suppress the nested display of individual fields. To \
1612 supply a summary to supplement the default structure add the -e option:"
1615 (lldb) type summary add -e --summary-string "*ptr = ${*var.ptr}" JustADemo
1618 "Now when displaying JustADemo values the int* is displayed, followed by the \
1619 standard LLDB sequence of children, one per line:"
1628 "You can also add summaries written in Python. These scripts use lldb public API to \
1629 gather information from your variables and produce a meaningful summary. To start a \
1630 multi-line script use the -P option. The function declaration will be displayed along with \
1631 a comment describing the two arguments. End your script with the word 'DONE' on a line by \
1635 (lldb) type summary add JustADemo -P
1636 def function (valobj,internal_dict):
1637 """valobj: an SBValue which you want to provide a summary for
1638 internal_dict: an LLDB support object not to be used"""
1639 value = valobj.GetChildMemberWithName('value');
1640 return 'My value is ' + value.GetValue();
1643 Alternatively, the -o option can be used when providing a simple one-line Python script:
1645 (lldb) type summary add JustADemo -o "value = valobj.GetChildMemberWithName('value'); return 'My value is ' + value.GetValue();")");
1648 bool CommandObjectTypeSummaryAdd::DoExecute(Args &command,
1649 CommandReturnObject &result) {
1650 WarnOnPotentialUnquotedUnsignedType(command, result);
1652 if (m_options.m_is_add_script) {
1653 #ifndef LLDB_DISABLE_PYTHON
1654 return Execute_ScriptSummary(command, result);
1656 result.AppendError("python is disabled");
1657 result.SetStatus(eReturnStatusFailed);
1659 #endif // LLDB_DISABLE_PYTHON
1662 return Execute_StringSummary(command, result);
1665 static bool FixArrayTypeNameWithRegex(ConstString &type_name) {
1666 llvm::StringRef type_name_ref(type_name.GetStringRef());
1668 if (type_name_ref.endswith("[]")) {
1669 std::string type_name_str(type_name.GetCString());
1670 type_name_str.resize(type_name_str.length() - 2);
1671 if (type_name_str.back() != ' ')
1672 type_name_str.append(" \\[[0-9]+\\]");
1674 type_name_str.append("\\[[0-9]+\\]");
1675 type_name.SetCString(type_name_str.c_str());
1681 bool CommandObjectTypeSummaryAdd::AddSummary(ConstString type_name,
1682 TypeSummaryImplSP entry,
1683 SummaryFormatType type,
1684 std::string category_name,
1686 lldb::TypeCategoryImplSP category;
1687 DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()),
1690 if (type == eRegularSummary) {
1691 if (FixArrayTypeNameWithRegex(type_name))
1692 type = eRegexSummary;
1695 if (type == eRegexSummary) {
1696 RegularExpressionSP typeRX(new RegularExpression());
1697 if (!typeRX->Compile(type_name.GetStringRef())) {
1699 error->SetErrorString(
1700 "regex format error (maybe this is not really a regex?)");
1704 category->GetRegexTypeSummariesContainer()->Delete(type_name);
1705 category->GetRegexTypeSummariesContainer()->Add(typeRX, entry);
1708 } else if (type == eNamedSummary) {
1709 // system named summaries do not exist (yet?)
1710 DataVisualization::NamedSummaryFormats::Add(type_name, entry);
1713 category->GetTypeSummariesContainer()->Add(type_name, entry);
1718 //-------------------------------------------------------------------------
1719 // CommandObjectTypeSummaryDelete
1720 //-------------------------------------------------------------------------
1722 class CommandObjectTypeSummaryDelete : public CommandObjectTypeFormatterDelete {
1724 CommandObjectTypeSummaryDelete(CommandInterpreter &interpreter)
1725 : CommandObjectTypeFormatterDelete(
1727 eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary,
1728 "type summary delete", "Delete an existing summary for a type.") {}
1730 ~CommandObjectTypeSummaryDelete() override = default;
1733 bool FormatterSpecificDeletion(ConstString typeCS) override {
1734 if (m_options.m_language != lldb::eLanguageTypeUnknown)
1736 return DataVisualization::NamedSummaryFormats::Delete(typeCS);
1740 class CommandObjectTypeSummaryClear : public CommandObjectTypeFormatterClear {
1742 CommandObjectTypeSummaryClear(CommandInterpreter &interpreter)
1743 : CommandObjectTypeFormatterClear(
1745 eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary,
1746 "type summary clear", "Delete all existing summaries.") {}
1749 void FormatterSpecificDeletion() override {
1750 DataVisualization::NamedSummaryFormats::Clear();
1754 //-------------------------------------------------------------------------
1755 // CommandObjectTypeSummaryList
1756 //-------------------------------------------------------------------------
1758 class CommandObjectTypeSummaryList
1759 : public CommandObjectTypeFormatterList<TypeSummaryImpl> {
1761 CommandObjectTypeSummaryList(CommandInterpreter &interpreter)
1762 : CommandObjectTypeFormatterList(interpreter, "type summary list",
1763 "Show a list of current summaries.") {}
1766 bool FormatterSpecificList(CommandReturnObject &result) override {
1767 if (DataVisualization::NamedSummaryFormats::GetCount() > 0) {
1768 result.GetOutputStream().Printf("Named summaries:\n");
1769 DataVisualization::NamedSummaryFormats::ForEach(
1770 [&result](ConstString name,
1771 const TypeSummaryImplSP &summary_sp) -> bool {
1772 result.GetOutputStream().Printf(
1773 "%s: %s\n", name.AsCString(),
1774 summary_sp->GetDescription().c_str());
1783 //-------------------------------------------------------------------------
1784 // CommandObjectTypeCategoryDefine
1785 //-------------------------------------------------------------------------
1787 static OptionDefinition g_type_category_define_options[] = {
1789 { LLDB_OPT_SET_ALL, false, "enabled", 'e', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "If specified, this category will be created enabled." },
1790 { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Specify the language that this category is supported for." }
1794 class CommandObjectTypeCategoryDefine : public CommandObjectParsed {
1795 class CommandOptions : public Options {
1798 : Options(), m_define_enabled(false, false),
1799 m_cate_language(eLanguageTypeUnknown, eLanguageTypeUnknown) {}
1801 ~CommandOptions() override = default;
1803 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1804 ExecutionContext *execution_context) override {
1806 const int short_option = m_getopt_table[option_idx].val;
1808 switch (short_option) {
1810 m_define_enabled.SetValueFromString(llvm::StringRef("true"));
1813 error = m_cate_language.SetValueFromString(option_arg);
1816 error.SetErrorStringWithFormat("unrecognized option '%c'",
1824 void OptionParsingStarting(ExecutionContext *execution_context) override {
1825 m_define_enabled.Clear();
1826 m_cate_language.Clear();
1829 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1830 return llvm::makeArrayRef(g_type_category_define_options);
1833 // Instance variables to hold the values for command options.
1835 OptionValueBoolean m_define_enabled;
1836 OptionValueLanguage m_cate_language;
1839 CommandOptions m_options;
1841 Options *GetOptions() override { return &m_options; }
1844 CommandObjectTypeCategoryDefine(CommandInterpreter &interpreter)
1845 : CommandObjectParsed(interpreter, "type category define",
1846 "Define a new category as a source of formatters.",
1849 CommandArgumentEntry type_arg;
1850 CommandArgumentData type_style_arg;
1852 type_style_arg.arg_type = eArgTypeName;
1853 type_style_arg.arg_repetition = eArgRepeatPlus;
1855 type_arg.push_back(type_style_arg);
1857 m_arguments.push_back(type_arg);
1860 ~CommandObjectTypeCategoryDefine() override = default;
1863 bool DoExecute(Args &command, CommandReturnObject &result) override {
1864 const size_t argc = command.GetArgumentCount();
1867 result.AppendErrorWithFormat("%s takes 1 or more args.\n",
1868 m_cmd_name.c_str());
1869 result.SetStatus(eReturnStatusFailed);
1873 for (auto &entry : command.entries()) {
1874 TypeCategoryImplSP category_sp;
1875 if (DataVisualization::Categories::GetCategory(ConstString(entry.ref),
1878 category_sp->AddLanguage(m_options.m_cate_language.GetCurrentValue());
1879 if (m_options.m_define_enabled.GetCurrentValue())
1880 DataVisualization::Categories::Enable(category_sp,
1881 TypeCategoryMap::Default);
1885 result.SetStatus(eReturnStatusSuccessFinishResult);
1886 return result.Succeeded();
1890 //-------------------------------------------------------------------------
1891 // CommandObjectTypeCategoryEnable
1892 //-------------------------------------------------------------------------
1894 static OptionDefinition g_type_category_enable_options[] = {
1896 { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Enable the category for this language." },
1900 class CommandObjectTypeCategoryEnable : public CommandObjectParsed {
1901 class CommandOptions : public Options {
1903 CommandOptions() : Options() {}
1905 ~CommandOptions() override = default;
1907 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1908 ExecutionContext *execution_context) override {
1910 const int short_option = m_getopt_table[option_idx].val;
1912 switch (short_option) {
1914 if (!option_arg.empty()) {
1915 m_language = Language::GetLanguageTypeFromString(option_arg);
1916 if (m_language == lldb::eLanguageTypeUnknown)
1917 error.SetErrorStringWithFormat("unrecognized language '%s'",
1918 option_arg.str().c_str());
1922 error.SetErrorStringWithFormat("unrecognized option '%c'",
1930 void OptionParsingStarting(ExecutionContext *execution_context) override {
1931 m_language = lldb::eLanguageTypeUnknown;
1934 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1935 return llvm::makeArrayRef(g_type_category_enable_options);
1938 // Instance variables to hold the values for command options.
1940 lldb::LanguageType m_language;
1943 CommandOptions m_options;
1945 Options *GetOptions() override { return &m_options; }
1948 CommandObjectTypeCategoryEnable(CommandInterpreter &interpreter)
1949 : CommandObjectParsed(interpreter, "type category enable",
1950 "Enable a category as a source of formatters.",
1953 CommandArgumentEntry type_arg;
1954 CommandArgumentData type_style_arg;
1956 type_style_arg.arg_type = eArgTypeName;
1957 type_style_arg.arg_repetition = eArgRepeatPlus;
1959 type_arg.push_back(type_style_arg);
1961 m_arguments.push_back(type_arg);
1964 ~CommandObjectTypeCategoryEnable() override = default;
1967 bool DoExecute(Args &command, CommandReturnObject &result) override {
1968 const size_t argc = command.GetArgumentCount();
1970 if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) {
1971 result.AppendErrorWithFormat("%s takes arguments and/or a language",
1972 m_cmd_name.c_str());
1973 result.SetStatus(eReturnStatusFailed);
1977 if (argc == 1 && strcmp(command.GetArgumentAtIndex(0), "*") == 0) {
1978 DataVisualization::Categories::EnableStar();
1979 } else if (argc > 0) {
1980 for (int i = argc - 1; i >= 0; i--) {
1981 const char *typeA = command.GetArgumentAtIndex(i);
1982 ConstString typeCS(typeA);
1985 result.AppendError("empty category name not allowed");
1986 result.SetStatus(eReturnStatusFailed);
1989 DataVisualization::Categories::Enable(typeCS);
1990 lldb::TypeCategoryImplSP cate;
1991 if (DataVisualization::Categories::GetCategory(typeCS, cate) && cate) {
1992 if (cate->GetCount() == 0) {
1993 result.AppendWarning("empty category enabled (typo?)");
1999 if (m_options.m_language != lldb::eLanguageTypeUnknown)
2000 DataVisualization::Categories::Enable(m_options.m_language);
2002 result.SetStatus(eReturnStatusSuccessFinishResult);
2003 return result.Succeeded();
2007 //-------------------------------------------------------------------------
2008 // CommandObjectTypeCategoryDelete
2009 //-------------------------------------------------------------------------
2011 class CommandObjectTypeCategoryDelete : public CommandObjectParsed {
2013 CommandObjectTypeCategoryDelete(CommandInterpreter &interpreter)
2014 : CommandObjectParsed(interpreter, "type category delete",
2015 "Delete a category and all associated formatters.",
2017 CommandArgumentEntry type_arg;
2018 CommandArgumentData type_style_arg;
2020 type_style_arg.arg_type = eArgTypeName;
2021 type_style_arg.arg_repetition = eArgRepeatPlus;
2023 type_arg.push_back(type_style_arg);
2025 m_arguments.push_back(type_arg);
2028 ~CommandObjectTypeCategoryDelete() override = default;
2031 bool DoExecute(Args &command, CommandReturnObject &result) override {
2032 const size_t argc = command.GetArgumentCount();
2035 result.AppendErrorWithFormat("%s takes 1 or more arg.\n",
2036 m_cmd_name.c_str());
2037 result.SetStatus(eReturnStatusFailed);
2041 bool success = true;
2043 // the order is not relevant here
2044 for (int i = argc - 1; i >= 0; i--) {
2045 const char *typeA = command.GetArgumentAtIndex(i);
2046 ConstString typeCS(typeA);
2049 result.AppendError("empty category name not allowed");
2050 result.SetStatus(eReturnStatusFailed);
2053 if (!DataVisualization::Categories::Delete(typeCS))
2054 success = false; // keep deleting even if we hit an error
2057 result.SetStatus(eReturnStatusSuccessFinishResult);
2058 return result.Succeeded();
2060 result.AppendError("cannot delete one or more categories\n");
2061 result.SetStatus(eReturnStatusFailed);
2067 //-------------------------------------------------------------------------
2068 // CommandObjectTypeCategoryDisable
2069 //-------------------------------------------------------------------------
2071 OptionDefinition g_type_category_disable_options[] = {
2073 { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Enable the category for this language." }
2077 class CommandObjectTypeCategoryDisable : public CommandObjectParsed {
2078 class CommandOptions : public Options {
2080 CommandOptions() : Options() {}
2082 ~CommandOptions() override = default;
2084 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2085 ExecutionContext *execution_context) override {
2087 const int short_option = m_getopt_table[option_idx].val;
2089 switch (short_option) {
2091 if (!option_arg.empty()) {
2092 m_language = Language::GetLanguageTypeFromString(option_arg);
2093 if (m_language == lldb::eLanguageTypeUnknown)
2094 error.SetErrorStringWithFormat("unrecognized language '%s'",
2095 option_arg.str().c_str());
2099 error.SetErrorStringWithFormat("unrecognized option '%c'",
2107 void OptionParsingStarting(ExecutionContext *execution_context) override {
2108 m_language = lldb::eLanguageTypeUnknown;
2111 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2112 return llvm::makeArrayRef(g_type_category_disable_options);
2115 // Instance variables to hold the values for command options.
2117 lldb::LanguageType m_language;
2120 CommandOptions m_options;
2122 Options *GetOptions() override { return &m_options; }
2125 CommandObjectTypeCategoryDisable(CommandInterpreter &interpreter)
2126 : CommandObjectParsed(interpreter, "type category disable",
2127 "Disable a category as a source of formatters.",
2130 CommandArgumentEntry type_arg;
2131 CommandArgumentData type_style_arg;
2133 type_style_arg.arg_type = eArgTypeName;
2134 type_style_arg.arg_repetition = eArgRepeatPlus;
2136 type_arg.push_back(type_style_arg);
2138 m_arguments.push_back(type_arg);
2141 ~CommandObjectTypeCategoryDisable() override = default;
2144 bool DoExecute(Args &command, CommandReturnObject &result) override {
2145 const size_t argc = command.GetArgumentCount();
2147 if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) {
2148 result.AppendErrorWithFormat("%s takes arguments and/or a language",
2149 m_cmd_name.c_str());
2150 result.SetStatus(eReturnStatusFailed);
2154 if (argc == 1 && strcmp(command.GetArgumentAtIndex(0), "*") == 0) {
2155 DataVisualization::Categories::DisableStar();
2156 } else if (argc > 0) {
2157 // the order is not relevant here
2158 for (int i = argc - 1; i >= 0; i--) {
2159 const char *typeA = command.GetArgumentAtIndex(i);
2160 ConstString typeCS(typeA);
2163 result.AppendError("empty category name not allowed");
2164 result.SetStatus(eReturnStatusFailed);
2167 DataVisualization::Categories::Disable(typeCS);
2171 if (m_options.m_language != lldb::eLanguageTypeUnknown)
2172 DataVisualization::Categories::Disable(m_options.m_language);
2174 result.SetStatus(eReturnStatusSuccessFinishResult);
2175 return result.Succeeded();
2179 //-------------------------------------------------------------------------
2180 // CommandObjectTypeCategoryList
2181 //-------------------------------------------------------------------------
2183 class CommandObjectTypeCategoryList : public CommandObjectParsed {
2185 CommandObjectTypeCategoryList(CommandInterpreter &interpreter)
2186 : CommandObjectParsed(interpreter, "type category list",
2187 "Provide a list of all existing categories.",
2189 CommandArgumentEntry type_arg;
2190 CommandArgumentData type_style_arg;
2192 type_style_arg.arg_type = eArgTypeName;
2193 type_style_arg.arg_repetition = eArgRepeatOptional;
2195 type_arg.push_back(type_style_arg);
2197 m_arguments.push_back(type_arg);
2200 ~CommandObjectTypeCategoryList() override = default;
2203 bool DoExecute(Args &command, CommandReturnObject &result) override {
2204 const size_t argc = command.GetArgumentCount();
2206 std::unique_ptr<RegularExpression> regex;
2209 regex.reset(new RegularExpression());
2210 const char *arg = command.GetArgumentAtIndex(0);
2211 if (!regex->Compile(llvm::StringRef::withNullAsEmpty(arg))) {
2212 result.AppendErrorWithFormat(
2213 "syntax error in category regular expression '%s'", arg);
2214 result.SetStatus(eReturnStatusFailed);
2217 } else if (argc != 0) {
2218 result.AppendErrorWithFormat("%s takes 0 or one arg.\n",
2219 m_cmd_name.c_str());
2220 result.SetStatus(eReturnStatusFailed);
2224 DataVisualization::Categories::ForEach(
2225 [®ex, &result](const lldb::TypeCategoryImplSP &category_sp) -> bool {
2228 if (regex->GetText() == category_sp->GetName()) {
2230 } else if (regex->Execute(llvm::StringRef::withNullAsEmpty(
2231 category_sp->GetName()))) {
2239 result.GetOutputStream().Printf(
2240 "Category: %s\n", category_sp->GetDescription().c_str());
2245 result.SetStatus(eReturnStatusSuccessFinishResult);
2246 return result.Succeeded();
2250 //-------------------------------------------------------------------------
2251 // CommandObjectTypeFilterList
2252 //-------------------------------------------------------------------------
2254 class CommandObjectTypeFilterList
2255 : public CommandObjectTypeFormatterList<TypeFilterImpl> {
2257 CommandObjectTypeFilterList(CommandInterpreter &interpreter)
2258 : CommandObjectTypeFormatterList(interpreter, "type filter list",
2259 "Show a list of current filters.") {}
2262 #ifndef LLDB_DISABLE_PYTHON
2264 //-------------------------------------------------------------------------
2265 // CommandObjectTypeSynthList
2266 //-------------------------------------------------------------------------
2268 class CommandObjectTypeSynthList
2269 : public CommandObjectTypeFormatterList<SyntheticChildren> {
2271 CommandObjectTypeSynthList(CommandInterpreter &interpreter)
2272 : CommandObjectTypeFormatterList(
2273 interpreter, "type synthetic list",
2274 "Show a list of current synthetic providers.") {}
2277 #endif // LLDB_DISABLE_PYTHON
2279 //-------------------------------------------------------------------------
2280 // CommandObjectTypeFilterDelete
2281 //-------------------------------------------------------------------------
2283 class CommandObjectTypeFilterDelete : public CommandObjectTypeFormatterDelete {
2285 CommandObjectTypeFilterDelete(CommandInterpreter &interpreter)
2286 : CommandObjectTypeFormatterDelete(
2288 eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter,
2289 "type filter delete", "Delete an existing filter for a type.") {}
2291 ~CommandObjectTypeFilterDelete() override = default;
2294 #ifndef LLDB_DISABLE_PYTHON
2296 //-------------------------------------------------------------------------
2297 // CommandObjectTypeSynthDelete
2298 //-------------------------------------------------------------------------
2300 class CommandObjectTypeSynthDelete : public CommandObjectTypeFormatterDelete {
2302 CommandObjectTypeSynthDelete(CommandInterpreter &interpreter)
2303 : CommandObjectTypeFormatterDelete(
2305 eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth,
2306 "type synthetic delete",
2307 "Delete an existing synthetic provider for a type.") {}
2309 ~CommandObjectTypeSynthDelete() override = default;
2312 #endif // LLDB_DISABLE_PYTHON
2314 //-------------------------------------------------------------------------
2315 // CommandObjectTypeFilterClear
2316 //-------------------------------------------------------------------------
2318 class CommandObjectTypeFilterClear : public CommandObjectTypeFormatterClear {
2320 CommandObjectTypeFilterClear(CommandInterpreter &interpreter)
2321 : CommandObjectTypeFormatterClear(
2323 eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter,
2324 "type filter clear", "Delete all existing filter.") {}
2327 #ifndef LLDB_DISABLE_PYTHON
2328 //-------------------------------------------------------------------------
2329 // CommandObjectTypeSynthClear
2330 //-------------------------------------------------------------------------
2332 class CommandObjectTypeSynthClear : public CommandObjectTypeFormatterClear {
2334 CommandObjectTypeSynthClear(CommandInterpreter &interpreter)
2335 : CommandObjectTypeFormatterClear(
2337 eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth,
2338 "type synthetic clear",
2339 "Delete all existing synthetic providers.") {}
2342 bool CommandObjectTypeSynthAdd::Execute_HandwritePython(
2343 Args &command, CommandReturnObject &result) {
2344 SynthAddOptions *options = new SynthAddOptions(
2345 m_options.m_skip_pointers, m_options.m_skip_references,
2346 m_options.m_cascade, m_options.m_regex, m_options.m_category);
2348 for (auto &entry : command.entries()) {
2349 if (entry.ref.empty()) {
2350 result.AppendError("empty typenames not allowed");
2351 result.SetStatus(eReturnStatusFailed);
2355 options->m_target_types << entry.ref;
2358 m_interpreter.GetPythonCommandsFromIOHandler(
2360 *this, // IOHandlerDelegate
2361 true, // Run IOHandler in async mode
2362 options); // Baton for the "io_handler" that will be passed back into our
2363 // IOHandlerDelegate functions
2364 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2365 return result.Succeeded();
2368 bool CommandObjectTypeSynthAdd::Execute_PythonClass(
2369 Args &command, CommandReturnObject &result) {
2370 const size_t argc = command.GetArgumentCount();
2373 result.AppendErrorWithFormat("%s takes one or more args.\n",
2374 m_cmd_name.c_str());
2375 result.SetStatus(eReturnStatusFailed);
2379 if (m_options.m_class_name.empty() && !m_options.m_input_python) {
2380 result.AppendErrorWithFormat("%s needs either a Python class name or -P to "
2381 "directly input Python code.\n",
2382 m_cmd_name.c_str());
2383 result.SetStatus(eReturnStatusFailed);
2387 SyntheticChildrenSP entry;
2389 ScriptedSyntheticChildren *impl = new ScriptedSyntheticChildren(
2390 SyntheticChildren::Flags()
2391 .SetCascades(m_options.m_cascade)
2392 .SetSkipPointers(m_options.m_skip_pointers)
2393 .SetSkipReferences(m_options.m_skip_references),
2394 m_options.m_class_name.c_str());
2398 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
2401 !interpreter->CheckObjectExists(impl->GetPythonClassName()))
2402 result.AppendWarning("The provided class does not exist - please define it "
2403 "before attempting to use this synthetic provider");
2405 // now I have a valid provider, let's add it to every type
2407 lldb::TypeCategoryImplSP category;
2408 DataVisualization::Categories::GetCategory(
2409 ConstString(m_options.m_category.c_str()), category);
2413 for (auto &arg_entry : command.entries()) {
2414 if (arg_entry.ref.empty()) {
2415 result.AppendError("empty typenames not allowed");
2416 result.SetStatus(eReturnStatusFailed);
2420 ConstString typeCS(arg_entry.ref);
2421 if (!AddSynth(typeCS, entry,
2422 m_options.m_regex ? eRegexSynth : eRegularSynth,
2423 m_options.m_category, &error)) {
2424 result.AppendError(error.AsCString());
2425 result.SetStatus(eReturnStatusFailed);
2430 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2431 return result.Succeeded();
2434 CommandObjectTypeSynthAdd::CommandObjectTypeSynthAdd(
2435 CommandInterpreter &interpreter)
2436 : CommandObjectParsed(interpreter, "type synthetic add",
2437 "Add a new synthetic provider for a type.", nullptr),
2438 IOHandlerDelegateMultiline("DONE"), m_options() {
2439 CommandArgumentEntry type_arg;
2440 CommandArgumentData type_style_arg;
2442 type_style_arg.arg_type = eArgTypeName;
2443 type_style_arg.arg_repetition = eArgRepeatPlus;
2445 type_arg.push_back(type_style_arg);
2447 m_arguments.push_back(type_arg);
2450 bool CommandObjectTypeSynthAdd::AddSynth(ConstString type_name,
2451 SyntheticChildrenSP entry,
2452 SynthFormatType type,
2453 std::string category_name,
2455 lldb::TypeCategoryImplSP category;
2456 DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()),
2459 if (type == eRegularSynth) {
2460 if (FixArrayTypeNameWithRegex(type_name))
2464 if (category->AnyMatches(type_name, eFormatCategoryItemFilter |
2465 eFormatCategoryItemRegexFilter,
2468 error->SetErrorStringWithFormat("cannot add synthetic for type %s when "
2469 "filter is defined in same category!",
2470 type_name.AsCString());
2474 if (type == eRegexSynth) {
2475 RegularExpressionSP typeRX(new RegularExpression());
2476 if (!typeRX->Compile(type_name.GetStringRef())) {
2478 error->SetErrorString(
2479 "regex format error (maybe this is not really a regex?)");
2483 category->GetRegexTypeSyntheticsContainer()->Delete(type_name);
2484 category->GetRegexTypeSyntheticsContainer()->Add(typeRX, entry);
2488 category->GetTypeSyntheticsContainer()->Add(type_name, entry);
2493 #endif // LLDB_DISABLE_PYTHON
2495 static OptionDefinition g_type_filter_add_options[] = {
2497 { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, cascade through typedef chains." },
2498 { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects." },
2499 { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for references-to-type objects." },
2500 { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Add this to the given category instead of the default one." },
2501 { LLDB_OPT_SET_ALL, false, "child", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpressionPath, "Include this expression path in the synthetic view." },
2502 { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Type names are actually regular expressions." }
2506 class CommandObjectTypeFilterAdd : public CommandObjectParsed {
2508 class CommandOptions : public Options {
2509 typedef std::vector<std::string> option_vector;
2512 CommandOptions() : Options() {}
2514 ~CommandOptions() override = default;
2516 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2517 ExecutionContext *execution_context) override {
2519 const int short_option = m_getopt_table[option_idx].val;
2522 switch (short_option) {
2524 m_cascade = OptionArgParser::ToBoolean(option_arg, true, &success);
2526 error.SetErrorStringWithFormat("invalid value for cascade: %s",
2527 option_arg.str().c_str());
2530 m_expr_paths.push_back(option_arg);
2531 has_child_list = true;
2534 m_skip_pointers = true;
2537 m_skip_references = true;
2540 m_category = std::string(option_arg);
2546 error.SetErrorStringWithFormat("unrecognized option '%c'",
2554 void OptionParsingStarting(ExecutionContext *execution_context) override {
2556 m_skip_pointers = false;
2557 m_skip_references = false;
2558 m_category = "default";
2559 m_expr_paths.clear();
2560 has_child_list = false;
2564 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2565 return llvm::makeArrayRef(g_type_filter_add_options);
2568 // Instance variables to hold the values for command options.
2571 bool m_skip_references;
2572 bool m_skip_pointers;
2573 bool m_input_python;
2574 option_vector m_expr_paths;
2575 std::string m_category;
2576 bool has_child_list;
2579 typedef option_vector::iterator ExpressionPathsIterator;
2582 CommandOptions m_options;
2584 Options *GetOptions() override { return &m_options; }
2586 enum FilterFormatType { eRegularFilter, eRegexFilter };
2588 bool AddFilter(ConstString type_name, TypeFilterImplSP entry,
2589 FilterFormatType type, std::string category_name,
2591 lldb::TypeCategoryImplSP category;
2592 DataVisualization::Categories::GetCategory(
2593 ConstString(category_name.c_str()), category);
2595 if (type == eRegularFilter) {
2596 if (FixArrayTypeNameWithRegex(type_name))
2597 type = eRegexFilter;
2600 if (category->AnyMatches(type_name, eFormatCategoryItemSynth |
2601 eFormatCategoryItemRegexSynth,
2604 error->SetErrorStringWithFormat("cannot add filter for type %s when "
2605 "synthetic is defined in same "
2607 type_name.AsCString());
2611 if (type == eRegexFilter) {
2612 RegularExpressionSP typeRX(new RegularExpression());
2613 if (!typeRX->Compile(type_name.GetStringRef())) {
2615 error->SetErrorString(
2616 "regex format error (maybe this is not really a regex?)");
2620 category->GetRegexTypeFiltersContainer()->Delete(type_name);
2621 category->GetRegexTypeFiltersContainer()->Add(typeRX, entry);
2625 category->GetTypeFiltersContainer()->Add(type_name, entry);
2631 CommandObjectTypeFilterAdd(CommandInterpreter &interpreter)
2632 : CommandObjectParsed(interpreter, "type filter add",
2633 "Add a new filter for a type.", nullptr),
2635 CommandArgumentEntry type_arg;
2636 CommandArgumentData type_style_arg;
2638 type_style_arg.arg_type = eArgTypeName;
2639 type_style_arg.arg_repetition = eArgRepeatPlus;
2641 type_arg.push_back(type_style_arg);
2643 m_arguments.push_back(type_arg);
2647 The following examples of 'type filter add' refer to this code snippet for context:
2662 Adding a simple filter:
2664 (lldb) type filter add --child a --child g Foo
2665 (lldb) frame variable my_foo
2668 "Produces output where only a and g are displayed. Other children of my_foo \
2669 (b, c, d, e, f, h and i) are available by asking for them explicitly:"
2672 (lldb) frame variable my_foo.b my_foo.c my_foo.i
2675 "The formatting option --raw on frame variable bypasses the filter, showing \
2676 all children of my_foo as if no filter was defined:"
2679 (lldb) frame variable my_foo --raw)");
2682 ~CommandObjectTypeFilterAdd() override = default;
2685 bool DoExecute(Args &command, CommandReturnObject &result) override {
2686 const size_t argc = command.GetArgumentCount();
2689 result.AppendErrorWithFormat("%s takes one or more args.\n",
2690 m_cmd_name.c_str());
2691 result.SetStatus(eReturnStatusFailed);
2695 if (m_options.m_expr_paths.empty()) {
2696 result.AppendErrorWithFormat("%s needs one or more children.\n",
2697 m_cmd_name.c_str());
2698 result.SetStatus(eReturnStatusFailed);
2702 TypeFilterImplSP entry(new TypeFilterImpl(
2703 SyntheticChildren::Flags()
2704 .SetCascades(m_options.m_cascade)
2705 .SetSkipPointers(m_options.m_skip_pointers)
2706 .SetSkipReferences(m_options.m_skip_references)));
2708 // go through the expression paths
2709 CommandOptions::ExpressionPathsIterator begin,
2710 end = m_options.m_expr_paths.end();
2712 for (begin = m_options.m_expr_paths.begin(); begin != end; begin++)
2713 entry->AddExpressionPath(*begin);
2715 // now I have a valid provider, let's add it to every type
2717 lldb::TypeCategoryImplSP category;
2718 DataVisualization::Categories::GetCategory(
2719 ConstString(m_options.m_category.c_str()), category);
2723 WarnOnPotentialUnquotedUnsignedType(command, result);
2725 for (auto &arg_entry : command.entries()) {
2726 if (arg_entry.ref.empty()) {
2727 result.AppendError("empty typenames not allowed");
2728 result.SetStatus(eReturnStatusFailed);
2732 ConstString typeCS(arg_entry.ref);
2733 if (!AddFilter(typeCS, entry,
2734 m_options.m_regex ? eRegexFilter : eRegularFilter,
2735 m_options.m_category, &error)) {
2736 result.AppendError(error.AsCString());
2737 result.SetStatus(eReturnStatusFailed);
2742 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2743 return result.Succeeded();
2747 //----------------------------------------------------------------------
2749 //----------------------------------------------------------------------
2750 static OptionDefinition g_type_lookup_options[] = {
2752 { LLDB_OPT_SET_ALL, false, "show-help", 'h', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display available help for types" },
2753 { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Which language's types should the search scope be" }
2757 class CommandObjectTypeLookup : public CommandObjectRaw {
2759 // this function is allowed to do a more aggressive job at guessing languages
2760 // than the expression parser is comfortable with - so leave the original
2761 // call alone and add one that is 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 Status 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(llvm::StringRef raw_command_line,
2866 CommandReturnObject &result) override {
2867 if (raw_command_line.empty()) {
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 OptionsWithRaw args(raw_command_line);
2877 const char *name_of_type = args.GetRawPart().c_str();
2880 if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group,
2885 // target_sp(GetCommandInterpreter().GetDebugger().GetSelectedTarget());
2886 // const bool fill_all_in = true;
2887 // ExecutionContext exe_ctx(target_sp.get(), fill_all_in);
2888 ExecutionContextScope *best_scope = exe_ctx.GetBestExecutionContextScope();
2890 bool any_found = false;
2892 std::vector<Language *> languages;
2894 bool is_global_search = false;
2895 LanguageType guessed_language = lldb::eLanguageTypeUnknown;
2897 if ((is_global_search =
2898 (m_command_options.m_language == eLanguageTypeUnknown))) {
2899 // FIXME: hardcoding languages is not good
2900 languages.push_back(Language::FindPlugin(eLanguageTypeObjC));
2901 languages.push_back(Language::FindPlugin(eLanguageTypeC_plus_plus));
2903 languages.push_back(Language::FindPlugin(m_command_options.m_language));
2906 // This is not the most efficient way to do this, but we support very few
2907 // languages so the cost of the sort is going to be dwarfed by the actual
2909 if (StackFrame *frame = m_exe_ctx.GetFramePtr()) {
2910 guessed_language = GuessLanguage(frame);
2911 if (guessed_language != eLanguageTypeUnknown) {
2913 languages.begin(), languages.end(),
2914 [guessed_language](Language *lang1, Language *lang2) -> bool {
2915 if (!lang1 || !lang2)
2917 LanguageType lt1 = lang1->GetLanguageType();
2918 LanguageType lt2 = lang2->GetLanguageType();
2919 if (lt1 == guessed_language)
2920 return true; // make the selected frame's language come first
2921 if (lt2 == guessed_language)
2922 return false; // make the selected frame's language come first
2923 return (lt1 < lt2); // normal comparison otherwise
2928 bool is_first_language = true;
2930 for (Language *language : languages) {
2934 if (auto scavenger = language->GetTypeScavenger()) {
2935 Language::TypeScavenger::ResultSet search_results;
2936 if (scavenger->Find(best_scope, name_of_type, search_results) > 0) {
2937 for (const auto &search_result : search_results) {
2938 if (search_result && search_result->IsValid()) {
2940 search_result->DumpToStream(result.GetOutputStream(),
2941 this->m_command_options.m_show_help);
2946 // this is "type lookup SomeName" and we did find a match, so get out
2947 if (any_found && is_global_search)
2949 else if (is_first_language && is_global_search &&
2950 guessed_language != lldb::eLanguageTypeUnknown) {
2951 is_first_language = false;
2952 result.GetOutputStream().Printf(
2953 "no type was found in the current language %s matching '%s'; "
2954 "performing a global search across all languages\n",
2955 Language::GetNameForLanguageType(guessed_language), name_of_type);
2960 result.AppendMessageWithFormat("no type was found matching '%s'\n",
2963 result.SetStatus(any_found ? lldb::eReturnStatusSuccessFinishResult
2964 : lldb::eReturnStatusSuccessFinishNoResult);
2969 template <typename FormatterType>
2970 class CommandObjectFormatterInfo : public CommandObjectRaw {
2972 typedef std::function<typename FormatterType::SharedPointer(ValueObject &)>
2974 CommandObjectFormatterInfo(CommandInterpreter &interpreter,
2975 const char *formatter_name,
2976 DiscoveryFunction discovery_func)
2977 : CommandObjectRaw(interpreter, "", "", "",
2978 eCommandRequiresFrame),
2979 m_formatter_name(formatter_name ? formatter_name : ""),
2980 m_discovery_function(discovery_func) {
2982 name.Printf("type %s info", formatter_name);
2983 SetCommandName(name.GetString());
2985 help.Printf("This command evaluates the provided expression and shows "
2986 "which %s is applied to the resulting value (if any).",
2988 SetHelp(help.GetString());
2989 StreamString syntax;
2990 syntax.Printf("type %s info <expr>", formatter_name);
2991 SetSyntax(syntax.GetString());
2994 ~CommandObjectFormatterInfo() override = default;
2997 bool DoExecute(llvm::StringRef command,
2998 CommandReturnObject &result) override {
2999 TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget();
3000 Thread *thread = GetDefaultThread();
3002 result.AppendError("no default thread");
3003 result.SetStatus(lldb::eReturnStatusFailed);
3007 StackFrameSP frame_sp = thread->GetSelectedFrame();
3008 ValueObjectSP result_valobj_sp;
3009 EvaluateExpressionOptions options;
3010 lldb::ExpressionResults expr_result = target_sp->EvaluateExpression(
3011 command, frame_sp.get(), result_valobj_sp, options);
3012 if (expr_result == eExpressionCompleted && result_valobj_sp) {
3014 result_valobj_sp->GetQualifiedRepresentationIfAvailable(
3015 target_sp->GetPreferDynamicValue(),
3016 target_sp->GetEnableSyntheticValue());
3017 typename FormatterType::SharedPointer formatter_sp =
3018 m_discovery_function(*result_valobj_sp);
3020 std::string description(formatter_sp->GetDescription());
3021 result.GetOutputStream()
3022 << m_formatter_name << " applied to ("
3023 << result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>")
3024 << ") " << command << " is: " << description << "\n";
3025 result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
3027 result.GetOutputStream()
3028 << "no " << m_formatter_name << " applies to ("
3029 << result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>")
3030 << ") " << command << "\n";
3031 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
3035 result.AppendError("failed to evaluate expression");
3036 result.SetStatus(lldb::eReturnStatusFailed);
3042 std::string m_formatter_name;
3043 DiscoveryFunction m_discovery_function;
3046 class CommandObjectTypeFormat : public CommandObjectMultiword {
3048 CommandObjectTypeFormat(CommandInterpreter &interpreter)
3049 : CommandObjectMultiword(
3050 interpreter, "type format",
3051 "Commands for customizing value display formats.",
3052 "type format [<sub-command-options>] ") {
3054 "add", CommandObjectSP(new CommandObjectTypeFormatAdd(interpreter)));
3055 LoadSubCommand("clear", CommandObjectSP(
3056 new CommandObjectTypeFormatClear(interpreter)));
3057 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFormatDelete(
3060 "list", CommandObjectSP(new CommandObjectTypeFormatList(interpreter)));
3062 "info", CommandObjectSP(new CommandObjectFormatterInfo<TypeFormatImpl>(
3063 interpreter, "format",
3064 [](ValueObject &valobj) -> TypeFormatImpl::SharedPointer {
3065 return valobj.GetValueFormat();
3069 ~CommandObjectTypeFormat() override = default;
3072 #ifndef LLDB_DISABLE_PYTHON
3074 class CommandObjectTypeSynth : public CommandObjectMultiword {
3076 CommandObjectTypeSynth(CommandInterpreter &interpreter)
3077 : CommandObjectMultiword(
3078 interpreter, "type synthetic",
3079 "Commands for operating on synthetic type representations.",
3080 "type synthetic [<sub-command-options>] ") {
3081 LoadSubCommand("add",
3082 CommandObjectSP(new CommandObjectTypeSynthAdd(interpreter)));
3084 "clear", CommandObjectSP(new CommandObjectTypeSynthClear(interpreter)));
3085 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSynthDelete(
3088 "list", CommandObjectSP(new CommandObjectTypeSynthList(interpreter)));
3091 CommandObjectSP(new CommandObjectFormatterInfo<SyntheticChildren>(
3092 interpreter, "synthetic",
3093 [](ValueObject &valobj) -> SyntheticChildren::SharedPointer {
3094 return valobj.GetSyntheticChildren();
3098 ~CommandObjectTypeSynth() override = default;
3101 #endif // LLDB_DISABLE_PYTHON
3103 class CommandObjectTypeFilter : public CommandObjectMultiword {
3105 CommandObjectTypeFilter(CommandInterpreter &interpreter)
3106 : CommandObjectMultiword(interpreter, "type filter",
3107 "Commands for operating on type filters.",
3108 "type synthetic [<sub-command-options>] ") {
3110 "add", CommandObjectSP(new CommandObjectTypeFilterAdd(interpreter)));
3111 LoadSubCommand("clear", CommandObjectSP(
3112 new CommandObjectTypeFilterClear(interpreter)));
3113 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFilterDelete(
3116 "list", CommandObjectSP(new CommandObjectTypeFilterList(interpreter)));
3119 ~CommandObjectTypeFilter() override = default;
3122 class CommandObjectTypeCategory : public CommandObjectMultiword {
3124 CommandObjectTypeCategory(CommandInterpreter &interpreter)
3125 : CommandObjectMultiword(interpreter, "type category",
3126 "Commands for operating on type categories.",
3127 "type category [<sub-command-options>] ") {
3130 CommandObjectSP(new CommandObjectTypeCategoryDefine(interpreter)));
3133 CommandObjectSP(new CommandObjectTypeCategoryEnable(interpreter)));
3136 CommandObjectSP(new CommandObjectTypeCategoryDisable(interpreter)));
3139 CommandObjectSP(new CommandObjectTypeCategoryDelete(interpreter)));
3140 LoadSubCommand("list", CommandObjectSP(
3141 new CommandObjectTypeCategoryList(interpreter)));
3144 ~CommandObjectTypeCategory() override = default;
3147 class CommandObjectTypeSummary : public CommandObjectMultiword {
3149 CommandObjectTypeSummary(CommandInterpreter &interpreter)
3150 : CommandObjectMultiword(
3151 interpreter, "type summary",
3152 "Commands for editing variable summary display options.",
3153 "type summary [<sub-command-options>] ") {
3155 "add", CommandObjectSP(new CommandObjectTypeSummaryAdd(interpreter)));
3156 LoadSubCommand("clear", CommandObjectSP(new CommandObjectTypeSummaryClear(
3158 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSummaryDelete(
3161 "list", CommandObjectSP(new CommandObjectTypeSummaryList(interpreter)));
3163 "info", CommandObjectSP(new CommandObjectFormatterInfo<TypeSummaryImpl>(
3164 interpreter, "summary",
3165 [](ValueObject &valobj) -> TypeSummaryImpl::SharedPointer {
3166 return valobj.GetSummaryFormat();
3170 ~CommandObjectTypeSummary() override = default;
3173 //-------------------------------------------------------------------------
3174 // CommandObjectType
3175 //-------------------------------------------------------------------------
3177 CommandObjectType::CommandObjectType(CommandInterpreter &interpreter)
3178 : CommandObjectMultiword(interpreter, "type",
3179 "Commands for operating on the type system.",
3180 "type [<sub-command-options>]") {
3181 LoadSubCommand("category",
3182 CommandObjectSP(new CommandObjectTypeCategory(interpreter)));
3183 LoadSubCommand("filter",
3184 CommandObjectSP(new CommandObjectTypeFilter(interpreter)));
3185 LoadSubCommand("format",
3186 CommandObjectSP(new CommandObjectTypeFormat(interpreter)));
3187 LoadSubCommand("summary",
3188 CommandObjectSP(new CommandObjectTypeSummary(interpreter)));
3189 #ifndef LLDB_DISABLE_PYTHON
3190 LoadSubCommand("synthetic",
3191 CommandObjectSP(new CommandObjectTypeSynth(interpreter)));
3192 #endif // LLDB_DISABLE_PYTHON
3193 LoadSubCommand("lookup",
3194 CommandObjectSP(new CommandObjectTypeLookup(interpreter)));
3197 CommandObjectType::~CommandObjectType() = default;