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"
16 #include "lldb/Core/Debugger.h"
17 #include "lldb/Core/IOHandler.h"
18 #include "lldb/DataFormatters/DataVisualization.h"
19 #include "lldb/Host/OptionParser.h"
20 #include "lldb/Interpreter/CommandInterpreter.h"
21 #include "lldb/Interpreter/CommandObject.h"
22 #include "lldb/Interpreter/CommandReturnObject.h"
23 #include "lldb/Interpreter/OptionArgParser.h"
24 #include "lldb/Interpreter/OptionGroupFormat.h"
25 #include "lldb/Interpreter/OptionValueBoolean.h"
26 #include "lldb/Interpreter/OptionValueLanguage.h"
27 #include "lldb/Interpreter/OptionValueString.h"
28 #include "lldb/Interpreter/Options.h"
29 #include "lldb/Symbol/Symbol.h"
30 #include "lldb/Target/Language.h"
31 #include "lldb/Target/Process.h"
32 #include "lldb/Target/StackFrame.h"
33 #include "lldb/Target/Target.h"
34 #include "lldb/Target/Thread.h"
35 #include "lldb/Target/ThreadList.h"
36 #include "lldb/Utility/ConstString.h"
37 #include "lldb/Utility/RegularExpression.h"
38 #include "lldb/Utility/State.h"
39 #include "lldb/Utility/StringList.h"
41 #include "llvm/ADT/STLExtras.h"
44 using namespace lldb_private;
46 class ScriptAddOptions {
48 TypeSummaryImpl::Flags m_flags;
49 StringList m_target_types;
52 std::string m_category;
54 ScriptAddOptions(const TypeSummaryImpl::Flags &flags, bool regx,
55 const ConstString &name, std::string catg)
56 : m_flags(flags), m_regex(regx), m_name(name), m_category(catg) {}
58 typedef std::shared_ptr<ScriptAddOptions> SharedPointer;
61 class SynthAddOptions {
64 bool m_skip_references;
67 StringList m_target_types;
68 std::string m_category;
70 SynthAddOptions(bool sptr, bool sref, bool casc, bool regx, std::string catg)
71 : m_skip_pointers(sptr), m_skip_references(sref), m_cascade(casc),
72 m_regex(regx), m_target_types(), m_category(catg) {}
74 typedef std::shared_ptr<SynthAddOptions> SharedPointer;
77 static bool WarnOnPotentialUnquotedUnsignedType(Args &command,
78 CommandReturnObject &result) {
82 for (auto entry : llvm::enumerate(command.entries().drop_back())) {
83 if (entry.value().ref != "unsigned")
85 auto next = command.entries()[entry.index() + 1].ref;
86 if (next == "int" || next == "short" || next == "char" || next == "long") {
87 result.AppendWarningWithFormat(
88 "unsigned %s being treated as two types. if you meant the combined "
90 "name use quotes, as in \"unsigned %s\"\n",
91 next.str().c_str(), next.str().c_str());
98 static constexpr OptionDefinition g_type_summary_add_options[] = {
100 { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeName, "Add this to the given category instead of the default one." },
101 { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "If true, cascade through typedef chains." },
102 { LLDB_OPT_SET_ALL, false, "no-value", 'v', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Don't show the value, just show the summary, for this type." },
103 { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects." },
104 { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Don't use this format for references-to-type objects." },
105 { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Type names are actually regular expressions." },
106 { LLDB_OPT_SET_1, true, "inline-children", 'c', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "If true, inline all child values into summary string." },
107 { LLDB_OPT_SET_1, false, "omit-names", 'O', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "If true, omit value names in the summary display." },
108 { LLDB_OPT_SET_2, true, "summary-string", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeSummaryString, "Summary string used to display text and object contents." },
109 { LLDB_OPT_SET_3, false, "python-script", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonScript, "Give a one-liner Python script as part of the command." },
110 { LLDB_OPT_SET_3, false, "python-function", 'F', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonFunction, "Give the name of a Python function to use for this type." },
111 { LLDB_OPT_SET_3, false, "input-python", 'P', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Input Python code to use for this type manually." },
112 { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "expand", 'e', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Expand aggregate data types to show children on separate lines." },
113 { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "hide-empty", 'h', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Do not expand aggregate data types with no children." },
114 { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeName, "A name for this summary string." }
118 class CommandObjectTypeSummaryAdd : public CommandObjectParsed,
119 public IOHandlerDelegateMultiline {
121 class CommandOptions : public Options {
123 CommandOptions(CommandInterpreter &interpreter) : Options() {}
125 ~CommandOptions() override = default;
127 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
128 ExecutionContext *execution_context) override;
130 void OptionParsingStarting(ExecutionContext *execution_context) override;
132 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
133 return llvm::makeArrayRef(g_type_summary_add_options);
136 // Instance variables to hold the values for command options.
138 TypeSummaryImpl::Flags m_flags;
140 std::string m_format_string;
142 std::string m_python_script;
143 std::string m_python_function;
144 bool m_is_add_script;
145 std::string m_category;
148 CommandOptions m_options;
150 Options *GetOptions() override { return &m_options; }
152 bool Execute_ScriptSummary(Args &command, CommandReturnObject &result);
154 bool Execute_StringSummary(Args &command, CommandReturnObject &result);
157 enum SummaryFormatType { eRegularSummary, eRegexSummary, eNamedSummary };
159 CommandObjectTypeSummaryAdd(CommandInterpreter &interpreter);
161 ~CommandObjectTypeSummaryAdd() override = default;
163 void IOHandlerActivated(IOHandler &io_handler) override {
164 static const char *g_summary_addreader_instructions =
165 "Enter your Python command(s). Type 'DONE' to end.\n"
166 "def function (valobj,internal_dict):\n"
167 " \"\"\"valobj: an SBValue which you want to provide a summary "
169 " internal_dict: an LLDB support object not to be used\"\"\"\n";
171 StreamFileSP output_sp(io_handler.GetOutputStreamFile());
173 output_sp->PutCString(g_summary_addreader_instructions);
178 void IOHandlerInputComplete(IOHandler &io_handler,
179 std::string &data) override {
180 StreamFileSP error_sp = io_handler.GetErrorStreamFile();
182 #ifndef LLDB_DISABLE_PYTHON
183 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
186 lines.SplitIntoLines(data);
187 if (lines.GetSize() > 0) {
188 ScriptAddOptions *options_ptr =
189 ((ScriptAddOptions *)io_handler.GetUserData());
191 ScriptAddOptions::SharedPointer options(
192 options_ptr); // this will ensure that we get rid of the pointer
193 // when going out of scope
195 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
197 std::string funct_name_str;
198 if (interpreter->GenerateTypeScriptFunction(lines,
200 if (funct_name_str.empty()) {
201 error_sp->Printf("unable to obtain a valid function name from "
202 "the script interpreter.\n");
205 // now I have a valid function name, let's add this as script
206 // for every type in the list
208 TypeSummaryImplSP script_format;
209 script_format.reset(new ScriptSummaryFormat(
210 options->m_flags, funct_name_str.c_str(),
211 lines.CopyList(" ").c_str()));
215 for (size_t i = 0; i < options->m_target_types.GetSize(); i++) {
216 const char *type_name =
217 options->m_target_types.GetStringAtIndex(i);
218 CommandObjectTypeSummaryAdd::AddSummary(
219 ConstString(type_name), script_format,
221 ? CommandObjectTypeSummaryAdd::eRegexSummary
222 : CommandObjectTypeSummaryAdd::eRegularSummary),
223 options->m_category, &error);
225 error_sp->Printf("error: %s", error.AsCString());
230 if (options->m_name) {
231 CommandObjectTypeSummaryAdd::AddSummary(
232 options->m_name, script_format,
233 CommandObjectTypeSummaryAdd::eNamedSummary,
234 options->m_category, &error);
236 CommandObjectTypeSummaryAdd::AddSummary(
237 options->m_name, script_format,
238 CommandObjectTypeSummaryAdd::eNamedSummary,
239 options->m_category, &error);
241 error_sp->Printf("error: %s", error.AsCString());
245 error_sp->Printf("error: %s", error.AsCString());
249 if (error.AsCString()) {
250 error_sp->Printf("error: %s", error.AsCString());
256 error_sp->Printf("error: unable to generate a function.\n");
260 error_sp->Printf("error: no script interpreter.\n");
264 error_sp->Printf("error: internal synchronization information "
265 "missing or invalid.\n");
269 error_sp->Printf("error: empty function, didn't add python command.\n");
274 "error: script interpreter missing, didn't add python command.\n");
277 #endif // LLDB_DISABLE_PYTHON
278 io_handler.SetIsDone(true);
281 static bool AddSummary(ConstString type_name, lldb::TypeSummaryImplSP entry,
282 SummaryFormatType type, std::string category,
283 Status *error = nullptr);
286 bool DoExecute(Args &command, CommandReturnObject &result) override;
289 static const char *g_synth_addreader_instructions =
290 "Enter your Python command(s). Type 'DONE' to end.\n"
291 "You must define a Python class with these methods:\n"
292 " def __init__(self, valobj, dict):\n"
293 " def num_children(self):\n"
294 " def get_child_at_index(self, index):\n"
295 " def get_child_index(self, name):\n"
296 " def update(self):\n"
298 "class synthProvider:\n";
300 static constexpr OptionDefinition g_type_synth_add_options[] = {
302 { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "If true, cascade through typedef chains." },
303 { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects." },
304 { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Don't use this format for references-to-type objects." },
305 { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeName, "Add this to the given category instead of the default one." },
306 { LLDB_OPT_SET_2, false, "python-class", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonClass, "Use this Python class to produce synthetic children." },
307 { LLDB_OPT_SET_3, false, "input-python", 'P', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Type Python code to generate a class that provides synthetic children." },
308 { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Type names are actually regular expressions." }
312 class CommandObjectTypeSynthAdd : public CommandObjectParsed,
313 public IOHandlerDelegateMultiline {
315 class CommandOptions : public Options {
317 CommandOptions() : Options() {}
319 ~CommandOptions() override = default;
321 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
322 ExecutionContext *execution_context) override {
324 const int short_option = m_getopt_table[option_idx].val;
327 switch (short_option) {
329 m_cascade = OptionArgParser::ToBoolean(option_arg, true, &success);
331 error.SetErrorStringWithFormat("invalid value for cascade: %s",
332 option_arg.str().c_str());
335 handwrite_python = true;
338 m_class_name = std::string(option_arg);
339 is_class_based = true;
342 m_skip_pointers = true;
345 m_skip_references = true;
348 m_category = std::string(option_arg);
354 error.SetErrorStringWithFormat("unrecognized option '%c'",
362 void OptionParsingStarting(ExecutionContext *execution_context) override {
365 m_skip_pointers = false;
366 m_skip_references = false;
367 m_category = "default";
368 is_class_based = false;
369 handwrite_python = false;
373 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
374 return llvm::makeArrayRef(g_type_synth_add_options);
377 // Instance variables to hold the values for command options.
380 bool m_skip_references;
381 bool m_skip_pointers;
382 std::string m_class_name;
384 std::string m_category;
386 bool handwrite_python;
390 CommandOptions m_options;
392 Options *GetOptions() override { return &m_options; }
394 bool Execute_HandwritePython(Args &command, CommandReturnObject &result);
396 bool Execute_PythonClass(Args &command, CommandReturnObject &result);
399 bool DoExecute(Args &command, CommandReturnObject &result) override {
400 WarnOnPotentialUnquotedUnsignedType(command, result);
402 if (m_options.handwrite_python)
403 return Execute_HandwritePython(command, result);
404 else if (m_options.is_class_based)
405 return Execute_PythonClass(command, result);
407 result.AppendError("must either provide a children list, a Python class "
408 "name, or use -P and type a Python class "
410 result.SetStatus(eReturnStatusFailed);
415 void IOHandlerActivated(IOHandler &io_handler) override {
416 StreamFileSP output_sp(io_handler.GetOutputStreamFile());
418 output_sp->PutCString(g_synth_addreader_instructions);
423 void IOHandlerInputComplete(IOHandler &io_handler,
424 std::string &data) override {
425 StreamFileSP error_sp = io_handler.GetErrorStreamFile();
427 #ifndef LLDB_DISABLE_PYTHON
428 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
431 lines.SplitIntoLines(data);
432 if (lines.GetSize() > 0) {
433 SynthAddOptions *options_ptr =
434 ((SynthAddOptions *)io_handler.GetUserData());
436 SynthAddOptions::SharedPointer options(
437 options_ptr); // this will ensure that we get rid of the pointer
438 // when going out of scope
440 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
442 std::string class_name_str;
443 if (interpreter->GenerateTypeSynthClass(lines, class_name_str)) {
444 if (class_name_str.empty()) {
446 "error: unable to obtain a proper name for the class.\n");
449 // everything should be fine now, let's add the synth provider
452 SyntheticChildrenSP synth_provider;
453 synth_provider.reset(new ScriptedSyntheticChildren(
454 SyntheticChildren::Flags()
455 .SetCascades(options->m_cascade)
456 .SetSkipPointers(options->m_skip_pointers)
457 .SetSkipReferences(options->m_skip_references),
458 class_name_str.c_str()));
460 lldb::TypeCategoryImplSP category;
461 DataVisualization::Categories::GetCategory(
462 ConstString(options->m_category.c_str()), category);
466 for (size_t i = 0; i < options->m_target_types.GetSize(); i++) {
467 const char *type_name =
468 options->m_target_types.GetStringAtIndex(i);
469 ConstString const_type_name(type_name);
470 if (const_type_name) {
471 if (!CommandObjectTypeSynthAdd::AddSynth(
472 const_type_name, synth_provider,
474 ? CommandObjectTypeSynthAdd::eRegexSynth
475 : CommandObjectTypeSynthAdd::eRegularSynth,
476 options->m_category, &error)) {
477 error_sp->Printf("error: %s\n", error.AsCString());
482 error_sp->Printf("error: invalid type name.\n");
489 error_sp->Printf("error: unable to generate a class.\n");
493 error_sp->Printf("error: no script interpreter.\n");
497 error_sp->Printf("error: internal synchronization data missing.\n");
501 error_sp->Printf("error: empty function, didn't add python command.\n");
506 "error: script interpreter missing, didn't add python command.\n");
510 #endif // LLDB_DISABLE_PYTHON
511 io_handler.SetIsDone(true);
515 enum SynthFormatType { eRegularSynth, eRegexSynth };
517 CommandObjectTypeSynthAdd(CommandInterpreter &interpreter);
519 ~CommandObjectTypeSynthAdd() override = default;
521 static bool AddSynth(ConstString type_name, lldb::SyntheticChildrenSP entry,
522 SynthFormatType type, std::string category_name,
526 //-------------------------------------------------------------------------
527 // CommandObjectTypeFormatAdd
528 //-------------------------------------------------------------------------
530 static constexpr OptionDefinition g_type_format_add_options[] = {
532 { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeName, "Add this to the given category instead of the default one." },
533 { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "If true, cascade through typedef chains." },
534 { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects." },
535 { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Don't use this format for references-to-type objects." },
536 { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Type names are actually regular expressions." },
537 { LLDB_OPT_SET_2, false, "type", 't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeName, "Format variables as if they were of this type." }
541 class CommandObjectTypeFormatAdd : public CommandObjectParsed {
543 class CommandOptions : public OptionGroup {
545 CommandOptions() : OptionGroup() {}
547 ~CommandOptions() override = default;
549 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
550 return llvm::makeArrayRef(g_type_format_add_options);
553 void OptionParsingStarting(ExecutionContext *execution_context) override {
555 m_skip_pointers = false;
556 m_skip_references = false;
558 m_category.assign("default");
559 m_custom_type_name.clear();
562 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
563 ExecutionContext *execution_context) override {
565 const int short_option =
566 g_type_format_add_options[option_idx].short_option;
569 switch (short_option) {
571 m_cascade = OptionArgParser::ToBoolean(option_value, true, &success);
573 error.SetErrorStringWithFormat("invalid value for cascade: %s",
574 option_value.str().c_str());
577 m_skip_pointers = true;
580 m_category.assign(option_value);
583 m_skip_references = true;
589 m_custom_type_name.assign(option_value);
592 error.SetErrorStringWithFormat("unrecognized option '%c'",
600 // Instance variables to hold the values for command options.
603 bool m_skip_references;
604 bool m_skip_pointers;
606 std::string m_category;
607 std::string m_custom_type_name;
610 OptionGroupOptions m_option_group;
611 OptionGroupFormat m_format_options;
612 CommandOptions m_command_options;
614 Options *GetOptions() override { return &m_option_group; }
617 CommandObjectTypeFormatAdd(CommandInterpreter &interpreter)
618 : CommandObjectParsed(interpreter, "type format add",
619 "Add a new formatting style for a type.", nullptr),
620 m_option_group(), m_format_options(eFormatInvalid),
621 m_command_options() {
622 CommandArgumentEntry type_arg;
623 CommandArgumentData type_style_arg;
625 type_style_arg.arg_type = eArgTypeName;
626 type_style_arg.arg_repetition = eArgRepeatPlus;
628 type_arg.push_back(type_style_arg);
630 m_arguments.push_back(type_arg);
634 The following examples of 'type format add' refer to this code snippet for context:
637 typedef float Afloat;
639 typedef Afloat Bfloat;
647 Adding default formatting:
649 (lldb) type format add -f hex AInt
650 (lldb) frame variable iy
653 " Produces hexadecimal display of iy, because no formatter is available for Bint and \
654 the one for Aint is used instead."
657 To prevent this use the cascade option '-C no' to prevent evaluation of typedef chains:
660 (lldb) type format add -f hex -C no AInt
662 Similar reasoning applies to this:
664 (lldb) type format add -f hex -C no float -p
667 " All float values and float references are now formatted as hexadecimal, but not \
668 pointers to floats. Nor will it change the default display for Afloat and Bfloat objects.");
670 // Add the "--format" to all options groups
671 m_option_group.Append(&m_format_options,
672 OptionGroupFormat::OPTION_GROUP_FORMAT,
674 m_option_group.Append(&m_command_options);
675 m_option_group.Finalize();
678 ~CommandObjectTypeFormatAdd() override = default;
681 bool DoExecute(Args &command, CommandReturnObject &result) override {
682 const size_t argc = command.GetArgumentCount();
685 result.AppendErrorWithFormat("%s takes one or more args.\n",
687 result.SetStatus(eReturnStatusFailed);
691 const Format format = m_format_options.GetFormat();
692 if (format == eFormatInvalid &&
693 m_command_options.m_custom_type_name.empty()) {
694 result.AppendErrorWithFormat("%s needs a valid format.\n",
696 result.SetStatus(eReturnStatusFailed);
700 TypeFormatImplSP entry;
702 if (m_command_options.m_custom_type_name.empty())
703 entry.reset(new TypeFormatImpl_Format(
704 format, TypeFormatImpl::Flags()
705 .SetCascades(m_command_options.m_cascade)
706 .SetSkipPointers(m_command_options.m_skip_pointers)
707 .SetSkipReferences(m_command_options.m_skip_references)));
709 entry.reset(new TypeFormatImpl_EnumType(
710 ConstString(m_command_options.m_custom_type_name.c_str()),
711 TypeFormatImpl::Flags()
712 .SetCascades(m_command_options.m_cascade)
713 .SetSkipPointers(m_command_options.m_skip_pointers)
714 .SetSkipReferences(m_command_options.m_skip_references)));
716 // now I have a valid format, let's add it to every type
718 TypeCategoryImplSP category_sp;
719 DataVisualization::Categories::GetCategory(
720 ConstString(m_command_options.m_category), category_sp);
724 WarnOnPotentialUnquotedUnsignedType(command, result);
726 for (auto &arg_entry : command.entries()) {
727 if (arg_entry.ref.empty()) {
728 result.AppendError("empty typenames not allowed");
729 result.SetStatus(eReturnStatusFailed);
733 ConstString typeCS(arg_entry.ref);
734 if (m_command_options.m_regex) {
735 RegularExpressionSP typeRX(new RegularExpression());
736 if (!typeRX->Compile(arg_entry.ref)) {
738 "regex format error (maybe this is not really a regex?)");
739 result.SetStatus(eReturnStatusFailed);
742 category_sp->GetRegexTypeSummariesContainer()->Delete(typeCS);
743 category_sp->GetRegexTypeFormatsContainer()->Add(typeRX, entry);
745 category_sp->GetTypeFormatsContainer()->Add(typeCS, entry);
748 result.SetStatus(eReturnStatusSuccessFinishNoResult);
749 return result.Succeeded();
753 static constexpr OptionDefinition g_type_formatter_delete_options[] = {
755 { LLDB_OPT_SET_1, false, "all", 'a', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Delete from every category." },
756 { LLDB_OPT_SET_2, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeName, "Delete from given category." },
757 { LLDB_OPT_SET_3, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Delete from given language's category." }
761 class CommandObjectTypeFormatterDelete : public CommandObjectParsed {
763 class CommandOptions : public Options {
765 CommandOptions() : Options() {}
767 ~CommandOptions() override = default;
769 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
770 ExecutionContext *execution_context) override {
772 const int short_option = m_getopt_table[option_idx].val;
774 switch (short_option) {
779 m_category = std::string(option_arg);
782 m_language = Language::GetLanguageTypeFromString(option_arg);
785 error.SetErrorStringWithFormat("unrecognized option '%c'",
793 void OptionParsingStarting(ExecutionContext *execution_context) override {
794 m_delete_all = false;
795 m_category = "default";
796 m_language = lldb::eLanguageTypeUnknown;
799 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
800 return llvm::makeArrayRef(g_type_formatter_delete_options);
803 // Instance variables to hold the values for command options.
806 std::string m_category;
807 lldb::LanguageType m_language;
810 CommandOptions m_options;
811 uint32_t m_formatter_kind_mask;
813 Options *GetOptions() override { return &m_options; }
816 CommandObjectTypeFormatterDelete(CommandInterpreter &interpreter,
817 uint32_t formatter_kind_mask,
818 const char *name, const char *help)
819 : CommandObjectParsed(interpreter, name, help, nullptr), m_options(),
820 m_formatter_kind_mask(formatter_kind_mask) {
821 CommandArgumentEntry type_arg;
822 CommandArgumentData type_style_arg;
824 type_style_arg.arg_type = eArgTypeName;
825 type_style_arg.arg_repetition = eArgRepeatPlain;
827 type_arg.push_back(type_style_arg);
829 m_arguments.push_back(type_arg);
832 ~CommandObjectTypeFormatterDelete() override = default;
835 virtual bool FormatterSpecificDeletion(ConstString typeCS) { return false; }
837 bool DoExecute(Args &command, CommandReturnObject &result) override {
838 const size_t argc = command.GetArgumentCount();
841 result.AppendErrorWithFormat("%s takes 1 arg.\n", m_cmd_name.c_str());
842 result.SetStatus(eReturnStatusFailed);
846 const char *typeA = command.GetArgumentAtIndex(0);
847 ConstString typeCS(typeA);
850 result.AppendError("empty typenames not allowed");
851 result.SetStatus(eReturnStatusFailed);
855 if (m_options.m_delete_all) {
856 DataVisualization::Categories::ForEach(
857 [this, typeCS](const lldb::TypeCategoryImplSP &category_sp) -> bool {
858 category_sp->Delete(typeCS, m_formatter_kind_mask);
861 result.SetStatus(eReturnStatusSuccessFinishNoResult);
862 return result.Succeeded();
865 bool delete_category = false;
866 bool extra_deletion = false;
868 if (m_options.m_language != lldb::eLanguageTypeUnknown) {
869 lldb::TypeCategoryImplSP category;
870 DataVisualization::Categories::GetCategory(m_options.m_language,
873 delete_category = category->Delete(typeCS, m_formatter_kind_mask);
874 extra_deletion = FormatterSpecificDeletion(typeCS);
876 lldb::TypeCategoryImplSP category;
877 DataVisualization::Categories::GetCategory(
878 ConstString(m_options.m_category.c_str()), category);
880 delete_category = category->Delete(typeCS, m_formatter_kind_mask);
881 extra_deletion = FormatterSpecificDeletion(typeCS);
884 if (delete_category || extra_deletion) {
885 result.SetStatus(eReturnStatusSuccessFinishNoResult);
886 return result.Succeeded();
888 result.AppendErrorWithFormat("no custom formatter for %s.\n", typeA);
889 result.SetStatus(eReturnStatusFailed);
895 static constexpr OptionDefinition g_type_formatter_clear_options[] = {
897 { LLDB_OPT_SET_ALL, false, "all", 'a', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Clear every category." }
901 class CommandObjectTypeFormatterClear : public CommandObjectParsed {
903 class CommandOptions : public Options {
905 CommandOptions() : Options() {}
907 ~CommandOptions() override = default;
909 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
910 ExecutionContext *execution_context) override {
912 const int short_option = m_getopt_table[option_idx].val;
914 switch (short_option) {
919 error.SetErrorStringWithFormat("unrecognized option '%c'",
927 void OptionParsingStarting(ExecutionContext *execution_context) override {
928 m_delete_all = false;
931 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
932 return llvm::makeArrayRef(g_type_formatter_clear_options);
935 // Instance variables to hold the values for command options.
939 CommandOptions m_options;
940 uint32_t m_formatter_kind_mask;
942 Options *GetOptions() override { return &m_options; }
945 CommandObjectTypeFormatterClear(CommandInterpreter &interpreter,
946 uint32_t formatter_kind_mask,
947 const char *name, const char *help)
948 : CommandObjectParsed(interpreter, name, help, nullptr), m_options(),
949 m_formatter_kind_mask(formatter_kind_mask) {}
951 ~CommandObjectTypeFormatterClear() override = default;
954 virtual void FormatterSpecificDeletion() {}
956 bool DoExecute(Args &command, CommandReturnObject &result) override {
957 if (m_options.m_delete_all) {
958 DataVisualization::Categories::ForEach(
959 [this](const TypeCategoryImplSP &category_sp) -> bool {
960 category_sp->Clear(m_formatter_kind_mask);
964 lldb::TypeCategoryImplSP category;
965 if (command.GetArgumentCount() > 0) {
966 const char *cat_name = command.GetArgumentAtIndex(0);
967 ConstString cat_nameCS(cat_name);
968 DataVisualization::Categories::GetCategory(cat_nameCS, category);
970 DataVisualization::Categories::GetCategory(ConstString(nullptr),
973 category->Clear(m_formatter_kind_mask);
976 FormatterSpecificDeletion();
978 result.SetStatus(eReturnStatusSuccessFinishResult);
979 return result.Succeeded();
983 //-------------------------------------------------------------------------
984 // CommandObjectTypeFormatDelete
985 //-------------------------------------------------------------------------
987 class CommandObjectTypeFormatDelete : public CommandObjectTypeFormatterDelete {
989 CommandObjectTypeFormatDelete(CommandInterpreter &interpreter)
990 : CommandObjectTypeFormatterDelete(
992 eFormatCategoryItemValue | eFormatCategoryItemRegexValue,
993 "type format delete",
994 "Delete an existing formatting style for a type.") {}
996 ~CommandObjectTypeFormatDelete() override = default;
999 //-------------------------------------------------------------------------
1000 // CommandObjectTypeFormatClear
1001 //-------------------------------------------------------------------------
1003 class CommandObjectTypeFormatClear : public CommandObjectTypeFormatterClear {
1005 CommandObjectTypeFormatClear(CommandInterpreter &interpreter)
1006 : CommandObjectTypeFormatterClear(
1008 eFormatCategoryItemValue | eFormatCategoryItemRegexValue,
1009 "type format clear", "Delete all existing format styles.") {}
1013 static constexpr OptionDefinition g_type_formatter_list_options[] = {
1015 {LLDB_OPT_SET_1, false, "category-regex", 'w', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeName, "Only show categories matching this filter."},
1016 {LLDB_OPT_SET_2, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Only show the category for a specific language."}
1020 template <typename FormatterType>
1021 class CommandObjectTypeFormatterList : public CommandObjectParsed {
1022 typedef typename FormatterType::SharedPointer FormatterSharedPointer;
1024 class CommandOptions : public Options {
1027 : Options(), m_category_regex("", ""),
1028 m_category_language(lldb::eLanguageTypeUnknown,
1029 lldb::eLanguageTypeUnknown) {}
1031 ~CommandOptions() override = default;
1033 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1034 ExecutionContext *execution_context) override {
1036 const int short_option = m_getopt_table[option_idx].val;
1037 switch (short_option) {
1039 m_category_regex.SetCurrentValue(option_arg);
1040 m_category_regex.SetOptionWasSet();
1043 error = m_category_language.SetValueFromString(option_arg);
1044 if (error.Success())
1045 m_category_language.SetOptionWasSet();
1048 error.SetErrorStringWithFormat("unrecognized option '%c'",
1056 void OptionParsingStarting(ExecutionContext *execution_context) override {
1057 m_category_regex.Clear();
1058 m_category_language.Clear();
1061 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1062 return llvm::makeArrayRef(g_type_formatter_list_options);
1065 // Instance variables to hold the values for command options.
1067 OptionValueString m_category_regex;
1068 OptionValueLanguage m_category_language;
1071 CommandOptions m_options;
1073 Options *GetOptions() override { return &m_options; }
1076 CommandObjectTypeFormatterList(CommandInterpreter &interpreter,
1077 const char *name, const char *help)
1078 : CommandObjectParsed(interpreter, name, help, nullptr), m_options() {
1079 CommandArgumentEntry type_arg;
1080 CommandArgumentData type_style_arg;
1082 type_style_arg.arg_type = eArgTypeName;
1083 type_style_arg.arg_repetition = eArgRepeatOptional;
1085 type_arg.push_back(type_style_arg);
1087 m_arguments.push_back(type_arg);
1090 ~CommandObjectTypeFormatterList() override = default;
1093 virtual bool FormatterSpecificList(CommandReturnObject &result) {
1097 bool DoExecute(Args &command, CommandReturnObject &result) override {
1098 const size_t argc = command.GetArgumentCount();
1100 std::unique_ptr<RegularExpression> category_regex;
1101 std::unique_ptr<RegularExpression> formatter_regex;
1103 if (m_options.m_category_regex.OptionWasSet()) {
1104 category_regex.reset(new RegularExpression());
1105 if (!category_regex->Compile(
1106 m_options.m_category_regex.GetCurrentValueAsRef())) {
1107 result.AppendErrorWithFormat(
1108 "syntax error in category regular expression '%s'",
1109 m_options.m_category_regex.GetCurrentValueAsRef().str().c_str());
1110 result.SetStatus(eReturnStatusFailed);
1116 const char *arg = command.GetArgumentAtIndex(0);
1117 formatter_regex.reset(new RegularExpression());
1118 if (!formatter_regex->Compile(llvm::StringRef::withNullAsEmpty(arg))) {
1119 result.AppendErrorWithFormat("syntax error in regular expression '%s'",
1121 result.SetStatus(eReturnStatusFailed);
1126 bool any_printed = false;
1128 auto category_closure = [&result, &formatter_regex, &any_printed](
1129 const lldb::TypeCategoryImplSP &category) -> void {
1130 result.GetOutputStream().Printf(
1131 "-----------------------\nCategory: %s%s\n-----------------------\n",
1132 category->GetName(), category->IsEnabled() ? "" : " (disabled)");
1134 TypeCategoryImpl::ForEachCallbacks<FormatterType> foreach;
1136 .SetExact([&result, &formatter_regex, &any_printed](
1138 const FormatterSharedPointer &format_sp) -> bool {
1139 if (formatter_regex) {
1141 if (name.GetStringRef() == formatter_regex->GetText()) {
1143 } else if (formatter_regex->Execute(name.GetStringRef())) {
1152 result.GetOutputStream().Printf("%s: %s\n", name.AsCString(),
1153 format_sp->GetDescription().c_str());
1158 .SetWithRegex([&result, &formatter_regex, &any_printed](
1159 RegularExpressionSP regex_sp,
1160 const FormatterSharedPointer &format_sp) -> bool {
1161 if (formatter_regex) {
1163 if (regex_sp->GetText() == formatter_regex->GetText()) {
1165 } else if (formatter_regex->Execute(regex_sp->GetText())) {
1174 result.GetOutputStream().Printf("%s: %s\n",
1175 regex_sp->GetText().str().c_str(),
1176 format_sp->GetDescription().c_str());
1180 category->ForEach(foreach);
1183 if (m_options.m_category_language.OptionWasSet()) {
1184 lldb::TypeCategoryImplSP category_sp;
1185 DataVisualization::Categories::GetCategory(
1186 m_options.m_category_language.GetCurrentValue(), category_sp);
1188 category_closure(category_sp);
1190 DataVisualization::Categories::ForEach(
1191 [&category_regex, &category_closure](
1192 const lldb::TypeCategoryImplSP &category) -> bool {
1193 if (category_regex) {
1195 if (category->GetName() == category_regex->GetText()) {
1197 } else if (category_regex->Execute(
1198 llvm::StringRef::withNullAsEmpty(
1199 category->GetName()))) {
1207 category_closure(category);
1212 any_printed = FormatterSpecificList(result) | any_printed;
1216 result.SetStatus(eReturnStatusSuccessFinishResult);
1218 result.GetOutputStream().PutCString("no matching results found.\n");
1219 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1221 return result.Succeeded();
1225 //-------------------------------------------------------------------------
1226 // CommandObjectTypeFormatList
1227 //-------------------------------------------------------------------------
1229 class CommandObjectTypeFormatList
1230 : public CommandObjectTypeFormatterList<TypeFormatImpl> {
1232 CommandObjectTypeFormatList(CommandInterpreter &interpreter)
1233 : CommandObjectTypeFormatterList(interpreter, "type format list",
1234 "Show a list of current formats.") {}
1237 #ifndef LLDB_DISABLE_PYTHON
1239 //-------------------------------------------------------------------------
1240 // CommandObjectTypeSummaryAdd
1241 //-------------------------------------------------------------------------
1243 #endif // LLDB_DISABLE_PYTHON
1245 Status CommandObjectTypeSummaryAdd::CommandOptions::SetOptionValue(
1246 uint32_t option_idx, llvm::StringRef option_arg,
1247 ExecutionContext *execution_context) {
1249 const int short_option = m_getopt_table[option_idx].val;
1252 switch (short_option) {
1254 m_flags.SetCascades(OptionArgParser::ToBoolean(option_arg, true, &success));
1256 error.SetErrorStringWithFormat("invalid value for cascade: %s",
1257 option_arg.str().c_str());
1260 m_flags.SetDontShowChildren(false);
1263 m_flags.SetHideEmptyAggregates(true);
1266 m_flags.SetDontShowValue(true);
1269 m_flags.SetShowMembersOneLiner(true);
1272 m_format_string = std::string(option_arg);
1275 m_flags.SetSkipPointers(true);
1278 m_flags.SetSkipReferences(true);
1284 m_name.SetString(option_arg);
1287 m_python_script = option_arg;
1288 m_is_add_script = true;
1291 m_python_function = option_arg;
1292 m_is_add_script = true;
1295 m_is_add_script = true;
1298 m_category = std::string(option_arg);
1301 m_flags.SetHideItemNames(true);
1304 error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
1311 void CommandObjectTypeSummaryAdd::CommandOptions::OptionParsingStarting(
1312 ExecutionContext *execution_context) {
1313 m_flags.Clear().SetCascades().SetDontShowChildren().SetDontShowValue(false);
1314 m_flags.SetShowMembersOneLiner(false)
1315 .SetSkipPointers(false)
1316 .SetSkipReferences(false)
1317 .SetHideItemNames(false);
1321 m_python_script = "";
1322 m_python_function = "";
1323 m_format_string = "";
1324 m_is_add_script = false;
1325 m_category = "default";
1328 #ifndef LLDB_DISABLE_PYTHON
1330 bool CommandObjectTypeSummaryAdd::Execute_ScriptSummary(
1331 Args &command, CommandReturnObject &result) {
1332 const size_t argc = command.GetArgumentCount();
1334 if (argc < 1 && !m_options.m_name) {
1335 result.AppendErrorWithFormat("%s takes one or more args.\n",
1336 m_cmd_name.c_str());
1337 result.SetStatus(eReturnStatusFailed);
1341 TypeSummaryImplSP script_format;
1343 if (!m_options.m_python_function
1344 .empty()) // we have a Python function ready to use
1346 const char *funct_name = m_options.m_python_function.c_str();
1347 if (!funct_name || !funct_name[0]) {
1348 result.AppendError("function name empty.\n");
1349 result.SetStatus(eReturnStatusFailed);
1354 (" " + m_options.m_python_function + "(valobj,internal_dict)");
1356 script_format.reset(
1357 new ScriptSummaryFormat(m_options.m_flags, funct_name, code.c_str()));
1359 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
1361 if (interpreter && !interpreter->CheckObjectExists(funct_name))
1362 result.AppendWarningWithFormat(
1363 "The provided function \"%s\" does not exist - "
1364 "please define it before attempting to use this summary.\n",
1366 } else if (!m_options.m_python_script
1367 .empty()) // we have a quick 1-line script, just use it
1369 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
1371 result.AppendError("script interpreter missing - unable to generate "
1372 "function wrapper.\n");
1373 result.SetStatus(eReturnStatusFailed);
1376 StringList funct_sl;
1377 funct_sl << m_options.m_python_script.c_str();
1378 std::string funct_name_str;
1379 if (!interpreter->GenerateTypeScriptFunction(funct_sl, funct_name_str)) {
1380 result.AppendError("unable to generate function wrapper.\n");
1381 result.SetStatus(eReturnStatusFailed);
1384 if (funct_name_str.empty()) {
1386 "script interpreter failed to generate a valid function name.\n");
1387 result.SetStatus(eReturnStatusFailed);
1391 std::string code = " " + m_options.m_python_script;
1393 script_format.reset(new ScriptSummaryFormat(
1394 m_options.m_flags, funct_name_str.c_str(), code.c_str()));
1396 // Use an IOHandler to grab Python code from the user
1397 ScriptAddOptions *options =
1398 new ScriptAddOptions(m_options.m_flags, m_options.m_regex,
1399 m_options.m_name, m_options.m_category);
1401 for (auto &entry : command.entries()) {
1402 if (entry.ref.empty()) {
1403 result.AppendError("empty typenames not allowed");
1404 result.SetStatus(eReturnStatusFailed);
1408 options->m_target_types << entry.ref;
1411 m_interpreter.GetPythonCommandsFromIOHandler(
1413 *this, // IOHandlerDelegate
1414 true, // Run IOHandler in async mode
1415 options); // Baton for the "io_handler" that will be passed back into
1416 // our IOHandlerDelegate functions
1417 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1419 return result.Succeeded();
1422 // if I am here, script_format must point to something good, so I can add
1423 // that as a script summary to all interested parties
1427 for (auto &entry : command.entries()) {
1428 CommandObjectTypeSummaryAdd::AddSummary(
1429 ConstString(entry.ref), script_format,
1430 (m_options.m_regex ? eRegexSummary : eRegularSummary),
1431 m_options.m_category, &error);
1433 result.AppendError(error.AsCString());
1434 result.SetStatus(eReturnStatusFailed);
1439 if (m_options.m_name) {
1440 AddSummary(m_options.m_name, script_format, eNamedSummary,
1441 m_options.m_category, &error);
1443 result.AppendError(error.AsCString());
1444 result.AppendError("added to types, but not given a name");
1445 result.SetStatus(eReturnStatusFailed);
1450 return result.Succeeded();
1453 #endif // LLDB_DISABLE_PYTHON
1455 bool CommandObjectTypeSummaryAdd::Execute_StringSummary(
1456 Args &command, CommandReturnObject &result) {
1457 const size_t argc = command.GetArgumentCount();
1459 if (argc < 1 && !m_options.m_name) {
1460 result.AppendErrorWithFormat("%s takes one or more args.\n",
1461 m_cmd_name.c_str());
1462 result.SetStatus(eReturnStatusFailed);
1466 if (!m_options.m_flags.GetShowMembersOneLiner() &&
1467 m_options.m_format_string.empty()) {
1468 result.AppendError("empty summary strings not allowed");
1469 result.SetStatus(eReturnStatusFailed);
1473 const char *format_cstr = (m_options.m_flags.GetShowMembersOneLiner()
1475 : m_options.m_format_string.c_str());
1477 // ${var%S} is an endless recursion, prevent it
1478 if (strcmp(format_cstr, "${var%S}") == 0) {
1479 result.AppendError("recursive summary not allowed");
1480 result.SetStatus(eReturnStatusFailed);
1484 std::unique_ptr<StringSummaryFormat> string_format(
1485 new StringSummaryFormat(m_options.m_flags, format_cstr));
1486 if (!string_format) {
1487 result.AppendError("summary creation failed");
1488 result.SetStatus(eReturnStatusFailed);
1491 if (string_format->m_error.Fail()) {
1492 result.AppendErrorWithFormat("syntax error: %s",
1493 string_format->m_error.AsCString("<unknown>"));
1494 result.SetStatus(eReturnStatusFailed);
1497 lldb::TypeSummaryImplSP entry(string_format.release());
1499 // now I have a valid format, let's add it to every type
1501 for (auto &arg_entry : command.entries()) {
1502 if (arg_entry.ref.empty()) {
1503 result.AppendError("empty typenames not allowed");
1504 result.SetStatus(eReturnStatusFailed);
1507 ConstString typeCS(arg_entry.ref);
1509 AddSummary(typeCS, entry,
1510 (m_options.m_regex ? eRegexSummary : eRegularSummary),
1511 m_options.m_category, &error);
1514 result.AppendError(error.AsCString());
1515 result.SetStatus(eReturnStatusFailed);
1520 if (m_options.m_name) {
1521 AddSummary(m_options.m_name, entry, eNamedSummary, m_options.m_category,
1524 result.AppendError(error.AsCString());
1525 result.AppendError("added to types, but not given a name");
1526 result.SetStatus(eReturnStatusFailed);
1531 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1532 return result.Succeeded();
1535 CommandObjectTypeSummaryAdd::CommandObjectTypeSummaryAdd(
1536 CommandInterpreter &interpreter)
1537 : CommandObjectParsed(interpreter, "type summary add",
1538 "Add a new summary style for a type.", nullptr),
1539 IOHandlerDelegateMultiline("DONE"), m_options(interpreter) {
1540 CommandArgumentEntry type_arg;
1541 CommandArgumentData type_style_arg;
1543 type_style_arg.arg_type = eArgTypeName;
1544 type_style_arg.arg_repetition = eArgRepeatPlus;
1546 type_arg.push_back(type_style_arg);
1548 m_arguments.push_back(type_arg);
1552 The following examples of 'type summary add' refer to this code snippet for context:
1558 JustADemo(int p = 1, float v = 0.1) : ptr(new int(p)), value(v) {}
1560 JustADemo demo_instance(42, 3.14);
1562 typedef JustADemo NewDemo;
1563 NewDemo new_demo_instance(42, 3.14);
1565 (lldb) type summary add --summary-string "the answer is ${*var.ptr}" JustADemo
1567 Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42"
1569 (lldb) type summary add --summary-string "the answer is ${*var.ptr}, and the question is ${var.value}" JustADemo
1571 Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42 and the question is 3.14"
1574 "Alternatively, you could define formatting for all pointers to integers and \
1575 rely on that when formatting JustADemo to obtain the same result:"
1578 (lldb) type summary add --summary-string "${var%V} -> ${*var}" "int *"
1579 (lldb) type summary add --summary-string "the answer is ${var.ptr}, and the question is ${var.value}" JustADemo
1582 "Type summaries are automatically applied to derived typedefs, so the examples \
1583 above apply to both JustADemo and NewDemo. The cascade option can be used to \
1584 suppress this behavior:"
1587 (lldb) type summary add --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo -C no
1589 The summary will now be used for values of JustADemo but not NewDemo.
1592 "By default summaries are shown for pointers and references to values of the \
1593 specified type. To suppress formatting for pointers use the -p option, or apply \
1594 the corresponding -r option to suppress formatting for references:"
1597 (lldb) type summary add -p -r --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo
1600 "One-line summaries including all fields in a type can be inferred without supplying an \
1601 explicit summary string by passing the -c option:"
1604 (lldb) type summary add -c JustADemo
1605 (lldb) frame variable demo_instance
1606 (ptr=<address>, value=3.14)
1609 "Type summaries normally suppress the nested display of individual fields. To \
1610 supply a summary to supplement the default structure add the -e option:"
1613 (lldb) type summary add -e --summary-string "*ptr = ${*var.ptr}" JustADemo
1616 "Now when displaying JustADemo values the int* is displayed, followed by the \
1617 standard LLDB sequence of children, one per line:"
1626 "You can also add summaries written in Python. These scripts use lldb public API to \
1627 gather information from your variables and produce a meaningful summary. To start a \
1628 multi-line script use the -P option. The function declaration will be displayed along with \
1629 a comment describing the two arguments. End your script with the word 'DONE' on a line by \
1633 (lldb) type summary add JustADemo -P
1634 def function (valobj,internal_dict):
1635 """valobj: an SBValue which you want to provide a summary for
1636 internal_dict: an LLDB support object not to be used"""
1637 value = valobj.GetChildMemberWithName('value');
1638 return 'My value is ' + value.GetValue();
1641 Alternatively, the -o option can be used when providing a simple one-line Python script:
1643 (lldb) type summary add JustADemo -o "value = valobj.GetChildMemberWithName('value'); return 'My value is ' + value.GetValue();")");
1646 bool CommandObjectTypeSummaryAdd::DoExecute(Args &command,
1647 CommandReturnObject &result) {
1648 WarnOnPotentialUnquotedUnsignedType(command, result);
1650 if (m_options.m_is_add_script) {
1651 #ifndef LLDB_DISABLE_PYTHON
1652 return Execute_ScriptSummary(command, result);
1654 result.AppendError("python is disabled");
1655 result.SetStatus(eReturnStatusFailed);
1657 #endif // LLDB_DISABLE_PYTHON
1660 return Execute_StringSummary(command, result);
1663 static bool FixArrayTypeNameWithRegex(ConstString &type_name) {
1664 llvm::StringRef type_name_ref(type_name.GetStringRef());
1666 if (type_name_ref.endswith("[]")) {
1667 std::string type_name_str(type_name.GetCString());
1668 type_name_str.resize(type_name_str.length() - 2);
1669 if (type_name_str.back() != ' ')
1670 type_name_str.append(" \\[[0-9]+\\]");
1672 type_name_str.append("\\[[0-9]+\\]");
1673 type_name.SetCString(type_name_str.c_str());
1679 bool CommandObjectTypeSummaryAdd::AddSummary(ConstString type_name,
1680 TypeSummaryImplSP entry,
1681 SummaryFormatType type,
1682 std::string category_name,
1684 lldb::TypeCategoryImplSP category;
1685 DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()),
1688 if (type == eRegularSummary) {
1689 if (FixArrayTypeNameWithRegex(type_name))
1690 type = eRegexSummary;
1693 if (type == eRegexSummary) {
1694 RegularExpressionSP typeRX(new RegularExpression());
1695 if (!typeRX->Compile(type_name.GetStringRef())) {
1697 error->SetErrorString(
1698 "regex format error (maybe this is not really a regex?)");
1702 category->GetRegexTypeSummariesContainer()->Delete(type_name);
1703 category->GetRegexTypeSummariesContainer()->Add(typeRX, entry);
1706 } else if (type == eNamedSummary) {
1707 // system named summaries do not exist (yet?)
1708 DataVisualization::NamedSummaryFormats::Add(type_name, entry);
1711 category->GetTypeSummariesContainer()->Add(type_name, entry);
1716 //-------------------------------------------------------------------------
1717 // CommandObjectTypeSummaryDelete
1718 //-------------------------------------------------------------------------
1720 class CommandObjectTypeSummaryDelete : public CommandObjectTypeFormatterDelete {
1722 CommandObjectTypeSummaryDelete(CommandInterpreter &interpreter)
1723 : CommandObjectTypeFormatterDelete(
1725 eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary,
1726 "type summary delete", "Delete an existing summary for a type.") {}
1728 ~CommandObjectTypeSummaryDelete() override = default;
1731 bool FormatterSpecificDeletion(ConstString typeCS) override {
1732 if (m_options.m_language != lldb::eLanguageTypeUnknown)
1734 return DataVisualization::NamedSummaryFormats::Delete(typeCS);
1738 class CommandObjectTypeSummaryClear : public CommandObjectTypeFormatterClear {
1740 CommandObjectTypeSummaryClear(CommandInterpreter &interpreter)
1741 : CommandObjectTypeFormatterClear(
1743 eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary,
1744 "type summary clear", "Delete all existing summaries.") {}
1747 void FormatterSpecificDeletion() override {
1748 DataVisualization::NamedSummaryFormats::Clear();
1752 //-------------------------------------------------------------------------
1753 // CommandObjectTypeSummaryList
1754 //-------------------------------------------------------------------------
1756 class CommandObjectTypeSummaryList
1757 : public CommandObjectTypeFormatterList<TypeSummaryImpl> {
1759 CommandObjectTypeSummaryList(CommandInterpreter &interpreter)
1760 : CommandObjectTypeFormatterList(interpreter, "type summary list",
1761 "Show a list of current summaries.") {}
1764 bool FormatterSpecificList(CommandReturnObject &result) override {
1765 if (DataVisualization::NamedSummaryFormats::GetCount() > 0) {
1766 result.GetOutputStream().Printf("Named summaries:\n");
1767 DataVisualization::NamedSummaryFormats::ForEach(
1768 [&result](ConstString name,
1769 const TypeSummaryImplSP &summary_sp) -> bool {
1770 result.GetOutputStream().Printf(
1771 "%s: %s\n", name.AsCString(),
1772 summary_sp->GetDescription().c_str());
1781 //-------------------------------------------------------------------------
1782 // CommandObjectTypeCategoryDefine
1783 //-------------------------------------------------------------------------
1785 static constexpr OptionDefinition g_type_category_define_options[] = {
1787 { LLDB_OPT_SET_ALL, false, "enabled", 'e', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "If specified, this category will be created enabled." },
1788 { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Specify the language that this category is supported for." }
1792 class CommandObjectTypeCategoryDefine : public CommandObjectParsed {
1793 class CommandOptions : public Options {
1796 : Options(), m_define_enabled(false, false),
1797 m_cate_language(eLanguageTypeUnknown, eLanguageTypeUnknown) {}
1799 ~CommandOptions() override = default;
1801 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1802 ExecutionContext *execution_context) override {
1804 const int short_option = m_getopt_table[option_idx].val;
1806 switch (short_option) {
1808 m_define_enabled.SetValueFromString(llvm::StringRef("true"));
1811 error = m_cate_language.SetValueFromString(option_arg);
1814 error.SetErrorStringWithFormat("unrecognized option '%c'",
1822 void OptionParsingStarting(ExecutionContext *execution_context) override {
1823 m_define_enabled.Clear();
1824 m_cate_language.Clear();
1827 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1828 return llvm::makeArrayRef(g_type_category_define_options);
1831 // Instance variables to hold the values for command options.
1833 OptionValueBoolean m_define_enabled;
1834 OptionValueLanguage m_cate_language;
1837 CommandOptions m_options;
1839 Options *GetOptions() override { return &m_options; }
1842 CommandObjectTypeCategoryDefine(CommandInterpreter &interpreter)
1843 : CommandObjectParsed(interpreter, "type category define",
1844 "Define a new category as a source of formatters.",
1847 CommandArgumentEntry type_arg;
1848 CommandArgumentData type_style_arg;
1850 type_style_arg.arg_type = eArgTypeName;
1851 type_style_arg.arg_repetition = eArgRepeatPlus;
1853 type_arg.push_back(type_style_arg);
1855 m_arguments.push_back(type_arg);
1858 ~CommandObjectTypeCategoryDefine() override = default;
1861 bool DoExecute(Args &command, CommandReturnObject &result) override {
1862 const size_t argc = command.GetArgumentCount();
1865 result.AppendErrorWithFormat("%s takes 1 or more args.\n",
1866 m_cmd_name.c_str());
1867 result.SetStatus(eReturnStatusFailed);
1871 for (auto &entry : command.entries()) {
1872 TypeCategoryImplSP category_sp;
1873 if (DataVisualization::Categories::GetCategory(ConstString(entry.ref),
1876 category_sp->AddLanguage(m_options.m_cate_language.GetCurrentValue());
1877 if (m_options.m_define_enabled.GetCurrentValue())
1878 DataVisualization::Categories::Enable(category_sp,
1879 TypeCategoryMap::Default);
1883 result.SetStatus(eReturnStatusSuccessFinishResult);
1884 return result.Succeeded();
1888 //-------------------------------------------------------------------------
1889 // CommandObjectTypeCategoryEnable
1890 //-------------------------------------------------------------------------
1892 static constexpr OptionDefinition g_type_category_enable_options[] = {
1894 { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Enable the category for this language." },
1898 class CommandObjectTypeCategoryEnable : public CommandObjectParsed {
1899 class CommandOptions : public Options {
1901 CommandOptions() : Options() {}
1903 ~CommandOptions() override = default;
1905 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1906 ExecutionContext *execution_context) override {
1908 const int short_option = m_getopt_table[option_idx].val;
1910 switch (short_option) {
1912 if (!option_arg.empty()) {
1913 m_language = Language::GetLanguageTypeFromString(option_arg);
1914 if (m_language == lldb::eLanguageTypeUnknown)
1915 error.SetErrorStringWithFormat("unrecognized language '%s'",
1916 option_arg.str().c_str());
1920 error.SetErrorStringWithFormat("unrecognized option '%c'",
1928 void OptionParsingStarting(ExecutionContext *execution_context) override {
1929 m_language = lldb::eLanguageTypeUnknown;
1932 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1933 return llvm::makeArrayRef(g_type_category_enable_options);
1936 // Instance variables to hold the values for command options.
1938 lldb::LanguageType m_language;
1941 CommandOptions m_options;
1943 Options *GetOptions() override { return &m_options; }
1946 CommandObjectTypeCategoryEnable(CommandInterpreter &interpreter)
1947 : CommandObjectParsed(interpreter, "type category enable",
1948 "Enable a category as a source of formatters.",
1951 CommandArgumentEntry type_arg;
1952 CommandArgumentData type_style_arg;
1954 type_style_arg.arg_type = eArgTypeName;
1955 type_style_arg.arg_repetition = eArgRepeatPlus;
1957 type_arg.push_back(type_style_arg);
1959 m_arguments.push_back(type_arg);
1962 ~CommandObjectTypeCategoryEnable() override = default;
1965 bool DoExecute(Args &command, CommandReturnObject &result) override {
1966 const size_t argc = command.GetArgumentCount();
1968 if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) {
1969 result.AppendErrorWithFormat("%s takes arguments and/or a language",
1970 m_cmd_name.c_str());
1971 result.SetStatus(eReturnStatusFailed);
1975 if (argc == 1 && strcmp(command.GetArgumentAtIndex(0), "*") == 0) {
1976 DataVisualization::Categories::EnableStar();
1977 } else if (argc > 0) {
1978 for (int i = argc - 1; i >= 0; i--) {
1979 const char *typeA = command.GetArgumentAtIndex(i);
1980 ConstString typeCS(typeA);
1983 result.AppendError("empty category name not allowed");
1984 result.SetStatus(eReturnStatusFailed);
1987 DataVisualization::Categories::Enable(typeCS);
1988 lldb::TypeCategoryImplSP cate;
1989 if (DataVisualization::Categories::GetCategory(typeCS, cate) && cate) {
1990 if (cate->GetCount() == 0) {
1991 result.AppendWarning("empty category enabled (typo?)");
1997 if (m_options.m_language != lldb::eLanguageTypeUnknown)
1998 DataVisualization::Categories::Enable(m_options.m_language);
2000 result.SetStatus(eReturnStatusSuccessFinishResult);
2001 return result.Succeeded();
2005 //-------------------------------------------------------------------------
2006 // CommandObjectTypeCategoryDelete
2007 //-------------------------------------------------------------------------
2009 class CommandObjectTypeCategoryDelete : public CommandObjectParsed {
2011 CommandObjectTypeCategoryDelete(CommandInterpreter &interpreter)
2012 : CommandObjectParsed(interpreter, "type category delete",
2013 "Delete a category and all associated formatters.",
2015 CommandArgumentEntry type_arg;
2016 CommandArgumentData type_style_arg;
2018 type_style_arg.arg_type = eArgTypeName;
2019 type_style_arg.arg_repetition = eArgRepeatPlus;
2021 type_arg.push_back(type_style_arg);
2023 m_arguments.push_back(type_arg);
2026 ~CommandObjectTypeCategoryDelete() override = default;
2029 bool DoExecute(Args &command, CommandReturnObject &result) override {
2030 const size_t argc = command.GetArgumentCount();
2033 result.AppendErrorWithFormat("%s takes 1 or more arg.\n",
2034 m_cmd_name.c_str());
2035 result.SetStatus(eReturnStatusFailed);
2039 bool success = true;
2041 // the order is not relevant here
2042 for (int i = argc - 1; i >= 0; i--) {
2043 const char *typeA = command.GetArgumentAtIndex(i);
2044 ConstString typeCS(typeA);
2047 result.AppendError("empty category name not allowed");
2048 result.SetStatus(eReturnStatusFailed);
2051 if (!DataVisualization::Categories::Delete(typeCS))
2052 success = false; // keep deleting even if we hit an error
2055 result.SetStatus(eReturnStatusSuccessFinishResult);
2056 return result.Succeeded();
2058 result.AppendError("cannot delete one or more categories\n");
2059 result.SetStatus(eReturnStatusFailed);
2065 //-------------------------------------------------------------------------
2066 // CommandObjectTypeCategoryDisable
2067 //-------------------------------------------------------------------------
2069 OptionDefinition constexpr g_type_category_disable_options[] = {
2071 { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Enable the category for this language." }
2075 class CommandObjectTypeCategoryDisable : public CommandObjectParsed {
2076 class CommandOptions : public Options {
2078 CommandOptions() : Options() {}
2080 ~CommandOptions() override = default;
2082 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2083 ExecutionContext *execution_context) override {
2085 const int short_option = m_getopt_table[option_idx].val;
2087 switch (short_option) {
2089 if (!option_arg.empty()) {
2090 m_language = Language::GetLanguageTypeFromString(option_arg);
2091 if (m_language == lldb::eLanguageTypeUnknown)
2092 error.SetErrorStringWithFormat("unrecognized language '%s'",
2093 option_arg.str().c_str());
2097 error.SetErrorStringWithFormat("unrecognized option '%c'",
2105 void OptionParsingStarting(ExecutionContext *execution_context) override {
2106 m_language = lldb::eLanguageTypeUnknown;
2109 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2110 return llvm::makeArrayRef(g_type_category_disable_options);
2113 // Instance variables to hold the values for command options.
2115 lldb::LanguageType m_language;
2118 CommandOptions m_options;
2120 Options *GetOptions() override { return &m_options; }
2123 CommandObjectTypeCategoryDisable(CommandInterpreter &interpreter)
2124 : CommandObjectParsed(interpreter, "type category disable",
2125 "Disable a category as a source of formatters.",
2128 CommandArgumentEntry type_arg;
2129 CommandArgumentData type_style_arg;
2131 type_style_arg.arg_type = eArgTypeName;
2132 type_style_arg.arg_repetition = eArgRepeatPlus;
2134 type_arg.push_back(type_style_arg);
2136 m_arguments.push_back(type_arg);
2139 ~CommandObjectTypeCategoryDisable() override = default;
2142 bool DoExecute(Args &command, CommandReturnObject &result) override {
2143 const size_t argc = command.GetArgumentCount();
2145 if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) {
2146 result.AppendErrorWithFormat("%s takes arguments and/or a language",
2147 m_cmd_name.c_str());
2148 result.SetStatus(eReturnStatusFailed);
2152 if (argc == 1 && strcmp(command.GetArgumentAtIndex(0), "*") == 0) {
2153 DataVisualization::Categories::DisableStar();
2154 } else if (argc > 0) {
2155 // the order is not relevant here
2156 for (int i = argc - 1; i >= 0; i--) {
2157 const char *typeA = command.GetArgumentAtIndex(i);
2158 ConstString typeCS(typeA);
2161 result.AppendError("empty category name not allowed");
2162 result.SetStatus(eReturnStatusFailed);
2165 DataVisualization::Categories::Disable(typeCS);
2169 if (m_options.m_language != lldb::eLanguageTypeUnknown)
2170 DataVisualization::Categories::Disable(m_options.m_language);
2172 result.SetStatus(eReturnStatusSuccessFinishResult);
2173 return result.Succeeded();
2177 //-------------------------------------------------------------------------
2178 // CommandObjectTypeCategoryList
2179 //-------------------------------------------------------------------------
2181 class CommandObjectTypeCategoryList : public CommandObjectParsed {
2183 CommandObjectTypeCategoryList(CommandInterpreter &interpreter)
2184 : CommandObjectParsed(interpreter, "type category list",
2185 "Provide a list of all existing categories.",
2187 CommandArgumentEntry type_arg;
2188 CommandArgumentData type_style_arg;
2190 type_style_arg.arg_type = eArgTypeName;
2191 type_style_arg.arg_repetition = eArgRepeatOptional;
2193 type_arg.push_back(type_style_arg);
2195 m_arguments.push_back(type_arg);
2198 ~CommandObjectTypeCategoryList() override = default;
2201 bool DoExecute(Args &command, CommandReturnObject &result) override {
2202 const size_t argc = command.GetArgumentCount();
2204 std::unique_ptr<RegularExpression> regex;
2207 regex.reset(new RegularExpression());
2208 const char *arg = command.GetArgumentAtIndex(0);
2209 if (!regex->Compile(llvm::StringRef::withNullAsEmpty(arg))) {
2210 result.AppendErrorWithFormat(
2211 "syntax error in category regular expression '%s'", arg);
2212 result.SetStatus(eReturnStatusFailed);
2215 } else if (argc != 0) {
2216 result.AppendErrorWithFormat("%s takes 0 or one arg.\n",
2217 m_cmd_name.c_str());
2218 result.SetStatus(eReturnStatusFailed);
2222 DataVisualization::Categories::ForEach(
2223 [®ex, &result](const lldb::TypeCategoryImplSP &category_sp) -> bool {
2226 if (regex->GetText() == category_sp->GetName()) {
2228 } else if (regex->Execute(llvm::StringRef::withNullAsEmpty(
2229 category_sp->GetName()))) {
2237 result.GetOutputStream().Printf(
2238 "Category: %s\n", category_sp->GetDescription().c_str());
2243 result.SetStatus(eReturnStatusSuccessFinishResult);
2244 return result.Succeeded();
2248 //-------------------------------------------------------------------------
2249 // CommandObjectTypeFilterList
2250 //-------------------------------------------------------------------------
2252 class CommandObjectTypeFilterList
2253 : public CommandObjectTypeFormatterList<TypeFilterImpl> {
2255 CommandObjectTypeFilterList(CommandInterpreter &interpreter)
2256 : CommandObjectTypeFormatterList(interpreter, "type filter list",
2257 "Show a list of current filters.") {}
2260 #ifndef LLDB_DISABLE_PYTHON
2262 //-------------------------------------------------------------------------
2263 // CommandObjectTypeSynthList
2264 //-------------------------------------------------------------------------
2266 class CommandObjectTypeSynthList
2267 : public CommandObjectTypeFormatterList<SyntheticChildren> {
2269 CommandObjectTypeSynthList(CommandInterpreter &interpreter)
2270 : CommandObjectTypeFormatterList(
2271 interpreter, "type synthetic list",
2272 "Show a list of current synthetic providers.") {}
2275 #endif // LLDB_DISABLE_PYTHON
2277 //-------------------------------------------------------------------------
2278 // CommandObjectTypeFilterDelete
2279 //-------------------------------------------------------------------------
2281 class CommandObjectTypeFilterDelete : public CommandObjectTypeFormatterDelete {
2283 CommandObjectTypeFilterDelete(CommandInterpreter &interpreter)
2284 : CommandObjectTypeFormatterDelete(
2286 eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter,
2287 "type filter delete", "Delete an existing filter for a type.") {}
2289 ~CommandObjectTypeFilterDelete() override = default;
2292 #ifndef LLDB_DISABLE_PYTHON
2294 //-------------------------------------------------------------------------
2295 // CommandObjectTypeSynthDelete
2296 //-------------------------------------------------------------------------
2298 class CommandObjectTypeSynthDelete : public CommandObjectTypeFormatterDelete {
2300 CommandObjectTypeSynthDelete(CommandInterpreter &interpreter)
2301 : CommandObjectTypeFormatterDelete(
2303 eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth,
2304 "type synthetic delete",
2305 "Delete an existing synthetic provider for a type.") {}
2307 ~CommandObjectTypeSynthDelete() override = default;
2310 #endif // LLDB_DISABLE_PYTHON
2312 //-------------------------------------------------------------------------
2313 // CommandObjectTypeFilterClear
2314 //-------------------------------------------------------------------------
2316 class CommandObjectTypeFilterClear : public CommandObjectTypeFormatterClear {
2318 CommandObjectTypeFilterClear(CommandInterpreter &interpreter)
2319 : CommandObjectTypeFormatterClear(
2321 eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter,
2322 "type filter clear", "Delete all existing filter.") {}
2325 #ifndef LLDB_DISABLE_PYTHON
2326 //-------------------------------------------------------------------------
2327 // CommandObjectTypeSynthClear
2328 //-------------------------------------------------------------------------
2330 class CommandObjectTypeSynthClear : public CommandObjectTypeFormatterClear {
2332 CommandObjectTypeSynthClear(CommandInterpreter &interpreter)
2333 : CommandObjectTypeFormatterClear(
2335 eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth,
2336 "type synthetic clear",
2337 "Delete all existing synthetic providers.") {}
2340 bool CommandObjectTypeSynthAdd::Execute_HandwritePython(
2341 Args &command, CommandReturnObject &result) {
2342 SynthAddOptions *options = new SynthAddOptions(
2343 m_options.m_skip_pointers, m_options.m_skip_references,
2344 m_options.m_cascade, m_options.m_regex, m_options.m_category);
2346 for (auto &entry : command.entries()) {
2347 if (entry.ref.empty()) {
2348 result.AppendError("empty typenames not allowed");
2349 result.SetStatus(eReturnStatusFailed);
2353 options->m_target_types << entry.ref;
2356 m_interpreter.GetPythonCommandsFromIOHandler(
2358 *this, // IOHandlerDelegate
2359 true, // Run IOHandler in async mode
2360 options); // Baton for the "io_handler" that will be passed back into our
2361 // IOHandlerDelegate functions
2362 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2363 return result.Succeeded();
2366 bool CommandObjectTypeSynthAdd::Execute_PythonClass(
2367 Args &command, CommandReturnObject &result) {
2368 const size_t argc = command.GetArgumentCount();
2371 result.AppendErrorWithFormat("%s takes one or more args.\n",
2372 m_cmd_name.c_str());
2373 result.SetStatus(eReturnStatusFailed);
2377 if (m_options.m_class_name.empty() && !m_options.m_input_python) {
2378 result.AppendErrorWithFormat("%s needs either a Python class name or -P to "
2379 "directly input Python code.\n",
2380 m_cmd_name.c_str());
2381 result.SetStatus(eReturnStatusFailed);
2385 SyntheticChildrenSP entry;
2387 ScriptedSyntheticChildren *impl = new ScriptedSyntheticChildren(
2388 SyntheticChildren::Flags()
2389 .SetCascades(m_options.m_cascade)
2390 .SetSkipPointers(m_options.m_skip_pointers)
2391 .SetSkipReferences(m_options.m_skip_references),
2392 m_options.m_class_name.c_str());
2396 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
2399 !interpreter->CheckObjectExists(impl->GetPythonClassName()))
2400 result.AppendWarning("The provided class does not exist - please define it "
2401 "before attempting to use this synthetic provider");
2403 // now I have a valid provider, let's add it to every type
2405 lldb::TypeCategoryImplSP category;
2406 DataVisualization::Categories::GetCategory(
2407 ConstString(m_options.m_category.c_str()), category);
2411 for (auto &arg_entry : command.entries()) {
2412 if (arg_entry.ref.empty()) {
2413 result.AppendError("empty typenames not allowed");
2414 result.SetStatus(eReturnStatusFailed);
2418 ConstString typeCS(arg_entry.ref);
2419 if (!AddSynth(typeCS, entry,
2420 m_options.m_regex ? eRegexSynth : eRegularSynth,
2421 m_options.m_category, &error)) {
2422 result.AppendError(error.AsCString());
2423 result.SetStatus(eReturnStatusFailed);
2428 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2429 return result.Succeeded();
2432 CommandObjectTypeSynthAdd::CommandObjectTypeSynthAdd(
2433 CommandInterpreter &interpreter)
2434 : CommandObjectParsed(interpreter, "type synthetic add",
2435 "Add a new synthetic provider for a type.", nullptr),
2436 IOHandlerDelegateMultiline("DONE"), m_options() {
2437 CommandArgumentEntry type_arg;
2438 CommandArgumentData type_style_arg;
2440 type_style_arg.arg_type = eArgTypeName;
2441 type_style_arg.arg_repetition = eArgRepeatPlus;
2443 type_arg.push_back(type_style_arg);
2445 m_arguments.push_back(type_arg);
2448 bool CommandObjectTypeSynthAdd::AddSynth(ConstString type_name,
2449 SyntheticChildrenSP entry,
2450 SynthFormatType type,
2451 std::string category_name,
2453 lldb::TypeCategoryImplSP category;
2454 DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()),
2457 if (type == eRegularSynth) {
2458 if (FixArrayTypeNameWithRegex(type_name))
2462 if (category->AnyMatches(type_name, eFormatCategoryItemFilter |
2463 eFormatCategoryItemRegexFilter,
2466 error->SetErrorStringWithFormat("cannot add synthetic for type %s when "
2467 "filter is defined in same category!",
2468 type_name.AsCString());
2472 if (type == eRegexSynth) {
2473 RegularExpressionSP typeRX(new RegularExpression());
2474 if (!typeRX->Compile(type_name.GetStringRef())) {
2476 error->SetErrorString(
2477 "regex format error (maybe this is not really a regex?)");
2481 category->GetRegexTypeSyntheticsContainer()->Delete(type_name);
2482 category->GetRegexTypeSyntheticsContainer()->Add(typeRX, entry);
2486 category->GetTypeSyntheticsContainer()->Add(type_name, entry);
2491 #endif // LLDB_DISABLE_PYTHON
2493 static constexpr OptionDefinition g_type_filter_add_options[] = {
2495 { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "If true, cascade through typedef chains." },
2496 { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects." },
2497 { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Don't use this format for references-to-type objects." },
2498 { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeName, "Add this to the given category instead of the default one." },
2499 { LLDB_OPT_SET_ALL, false, "child", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeExpressionPath, "Include this expression path in the synthetic view." },
2500 { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Type names are actually regular expressions." }
2504 class CommandObjectTypeFilterAdd : public CommandObjectParsed {
2506 class CommandOptions : public Options {
2507 typedef std::vector<std::string> option_vector;
2510 CommandOptions() : Options() {}
2512 ~CommandOptions() override = default;
2514 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2515 ExecutionContext *execution_context) override {
2517 const int short_option = m_getopt_table[option_idx].val;
2520 switch (short_option) {
2522 m_cascade = OptionArgParser::ToBoolean(option_arg, true, &success);
2524 error.SetErrorStringWithFormat("invalid value for cascade: %s",
2525 option_arg.str().c_str());
2528 m_expr_paths.push_back(option_arg);
2529 has_child_list = true;
2532 m_skip_pointers = true;
2535 m_skip_references = true;
2538 m_category = std::string(option_arg);
2544 error.SetErrorStringWithFormat("unrecognized option '%c'",
2552 void OptionParsingStarting(ExecutionContext *execution_context) override {
2554 m_skip_pointers = false;
2555 m_skip_references = false;
2556 m_category = "default";
2557 m_expr_paths.clear();
2558 has_child_list = false;
2562 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2563 return llvm::makeArrayRef(g_type_filter_add_options);
2566 // Instance variables to hold the values for command options.
2569 bool m_skip_references;
2570 bool m_skip_pointers;
2571 bool m_input_python;
2572 option_vector m_expr_paths;
2573 std::string m_category;
2574 bool has_child_list;
2577 typedef option_vector::iterator ExpressionPathsIterator;
2580 CommandOptions m_options;
2582 Options *GetOptions() override { return &m_options; }
2584 enum FilterFormatType { eRegularFilter, eRegexFilter };
2586 bool AddFilter(ConstString type_name, TypeFilterImplSP entry,
2587 FilterFormatType type, std::string category_name,
2589 lldb::TypeCategoryImplSP category;
2590 DataVisualization::Categories::GetCategory(
2591 ConstString(category_name.c_str()), category);
2593 if (type == eRegularFilter) {
2594 if (FixArrayTypeNameWithRegex(type_name))
2595 type = eRegexFilter;
2598 if (category->AnyMatches(type_name, eFormatCategoryItemSynth |
2599 eFormatCategoryItemRegexSynth,
2602 error->SetErrorStringWithFormat("cannot add filter for type %s when "
2603 "synthetic is defined in same "
2605 type_name.AsCString());
2609 if (type == eRegexFilter) {
2610 RegularExpressionSP typeRX(new RegularExpression());
2611 if (!typeRX->Compile(type_name.GetStringRef())) {
2613 error->SetErrorString(
2614 "regex format error (maybe this is not really a regex?)");
2618 category->GetRegexTypeFiltersContainer()->Delete(type_name);
2619 category->GetRegexTypeFiltersContainer()->Add(typeRX, entry);
2623 category->GetTypeFiltersContainer()->Add(type_name, entry);
2629 CommandObjectTypeFilterAdd(CommandInterpreter &interpreter)
2630 : CommandObjectParsed(interpreter, "type filter add",
2631 "Add a new filter for a type.", nullptr),
2633 CommandArgumentEntry type_arg;
2634 CommandArgumentData type_style_arg;
2636 type_style_arg.arg_type = eArgTypeName;
2637 type_style_arg.arg_repetition = eArgRepeatPlus;
2639 type_arg.push_back(type_style_arg);
2641 m_arguments.push_back(type_arg);
2645 The following examples of 'type filter add' refer to this code snippet for context:
2660 Adding a simple filter:
2662 (lldb) type filter add --child a --child g Foo
2663 (lldb) frame variable my_foo
2666 "Produces output where only a and g are displayed. Other children of my_foo \
2667 (b, c, d, e, f, h and i) are available by asking for them explicitly:"
2670 (lldb) frame variable my_foo.b my_foo.c my_foo.i
2673 "The formatting option --raw on frame variable bypasses the filter, showing \
2674 all children of my_foo as if no filter was defined:"
2677 (lldb) frame variable my_foo --raw)");
2680 ~CommandObjectTypeFilterAdd() override = default;
2683 bool DoExecute(Args &command, CommandReturnObject &result) override {
2684 const size_t argc = command.GetArgumentCount();
2687 result.AppendErrorWithFormat("%s takes one or more args.\n",
2688 m_cmd_name.c_str());
2689 result.SetStatus(eReturnStatusFailed);
2693 if (m_options.m_expr_paths.empty()) {
2694 result.AppendErrorWithFormat("%s needs one or more children.\n",
2695 m_cmd_name.c_str());
2696 result.SetStatus(eReturnStatusFailed);
2700 TypeFilterImplSP entry(new TypeFilterImpl(
2701 SyntheticChildren::Flags()
2702 .SetCascades(m_options.m_cascade)
2703 .SetSkipPointers(m_options.m_skip_pointers)
2704 .SetSkipReferences(m_options.m_skip_references)));
2706 // go through the expression paths
2707 CommandOptions::ExpressionPathsIterator begin,
2708 end = m_options.m_expr_paths.end();
2710 for (begin = m_options.m_expr_paths.begin(); begin != end; begin++)
2711 entry->AddExpressionPath(*begin);
2713 // now I have a valid provider, let's add it to every type
2715 lldb::TypeCategoryImplSP category;
2716 DataVisualization::Categories::GetCategory(
2717 ConstString(m_options.m_category.c_str()), category);
2721 WarnOnPotentialUnquotedUnsignedType(command, result);
2723 for (auto &arg_entry : command.entries()) {
2724 if (arg_entry.ref.empty()) {
2725 result.AppendError("empty typenames not allowed");
2726 result.SetStatus(eReturnStatusFailed);
2730 ConstString typeCS(arg_entry.ref);
2731 if (!AddFilter(typeCS, entry,
2732 m_options.m_regex ? eRegexFilter : eRegularFilter,
2733 m_options.m_category, &error)) {
2734 result.AppendError(error.AsCString());
2735 result.SetStatus(eReturnStatusFailed);
2740 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2741 return result.Succeeded();
2745 //----------------------------------------------------------------------
2747 //----------------------------------------------------------------------
2748 static constexpr OptionDefinition g_type_lookup_options[] = {
2750 { LLDB_OPT_SET_ALL, false, "show-help", 'h', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Display available help for types" },
2751 { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Which language's types should the search scope be" }
2755 class CommandObjectTypeLookup : public CommandObjectRaw {
2757 // this function is allowed to do a more aggressive job at guessing languages
2758 // than the expression parser is comfortable with - so leave the original
2759 // call alone and add one that is specific to type lookup
2760 lldb::LanguageType GuessLanguage(StackFrame *frame) {
2761 lldb::LanguageType lang_type = lldb::eLanguageTypeUnknown;
2766 lang_type = frame->GuessLanguage();
2767 if (lang_type != lldb::eLanguageTypeUnknown)
2770 Symbol *s = frame->GetSymbolContext(eSymbolContextSymbol).symbol;
2772 lang_type = s->GetMangled().GuessLanguage();
2777 class CommandOptions : public OptionGroup {
2780 : OptionGroup(), m_show_help(false), m_language(eLanguageTypeUnknown) {}
2782 ~CommandOptions() override = default;
2784 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2785 return llvm::makeArrayRef(g_type_lookup_options);
2788 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
2789 ExecutionContext *execution_context) override {
2792 const int short_option = g_type_lookup_options[option_idx].short_option;
2794 switch (short_option) {
2800 m_language = Language::GetLanguageTypeFromString(option_value);
2804 error.SetErrorStringWithFormat("invalid short option character '%c'",
2812 void OptionParsingStarting(ExecutionContext *execution_context) override {
2813 m_show_help = false;
2814 m_language = eLanguageTypeUnknown;
2817 // Options table: Required for subclasses of Options.
2820 lldb::LanguageType m_language;
2823 OptionGroupOptions m_option_group;
2824 CommandOptions m_command_options;
2827 CommandObjectTypeLookup(CommandInterpreter &interpreter)
2828 : CommandObjectRaw(interpreter, "type lookup",
2829 "Lookup types and declarations in the current target, "
2830 "following language-specific naming conventions.",
2831 "type lookup <type-specifier>",
2832 eCommandRequiresTarget),
2833 m_option_group(), m_command_options() {
2834 m_option_group.Append(&m_command_options);
2835 m_option_group.Finalize();
2838 ~CommandObjectTypeLookup() override = default;
2840 Options *GetOptions() override { return &m_option_group; }
2842 llvm::StringRef GetHelpLong() override {
2843 if (!m_cmd_help_long.empty())
2844 return m_cmd_help_long;
2846 StreamString stream;
2847 // FIXME: hardcoding languages is not good
2848 lldb::LanguageType languages[] = {eLanguageTypeObjC,
2849 eLanguageTypeC_plus_plus};
2851 for (const auto lang_type : languages) {
2852 if (auto language = Language::FindPlugin(lang_type)) {
2853 if (const char *help = language->GetLanguageSpecificTypeLookupHelp()) {
2854 stream.Printf("%s\n", help);
2859 m_cmd_help_long = stream.GetString();
2860 return m_cmd_help_long;
2863 bool DoExecute(llvm::StringRef raw_command_line,
2864 CommandReturnObject &result) override {
2865 if (raw_command_line.empty()) {
2867 "type lookup cannot be invoked without a type name as argument");
2871 auto exe_ctx = GetCommandInterpreter().GetExecutionContext();
2872 m_option_group.NotifyOptionParsingStarting(&exe_ctx);
2874 OptionsWithRaw args(raw_command_line);
2875 const char *name_of_type = args.GetRawPart().c_str();
2878 if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group,
2883 // target_sp(GetCommandInterpreter().GetDebugger().GetSelectedTarget());
2884 // const bool fill_all_in = true;
2885 // ExecutionContext exe_ctx(target_sp.get(), fill_all_in);
2886 ExecutionContextScope *best_scope = exe_ctx.GetBestExecutionContextScope();
2888 bool any_found = false;
2890 std::vector<Language *> languages;
2892 bool is_global_search = false;
2893 LanguageType guessed_language = lldb::eLanguageTypeUnknown;
2895 if ((is_global_search =
2896 (m_command_options.m_language == eLanguageTypeUnknown))) {
2897 // FIXME: hardcoding languages is not good
2898 languages.push_back(Language::FindPlugin(eLanguageTypeObjC));
2899 languages.push_back(Language::FindPlugin(eLanguageTypeC_plus_plus));
2901 languages.push_back(Language::FindPlugin(m_command_options.m_language));
2904 // This is not the most efficient way to do this, but we support very few
2905 // languages so the cost of the sort is going to be dwarfed by the actual
2907 if (StackFrame *frame = m_exe_ctx.GetFramePtr()) {
2908 guessed_language = GuessLanguage(frame);
2909 if (guessed_language != eLanguageTypeUnknown) {
2911 languages.begin(), languages.end(),
2912 [guessed_language](Language *lang1, Language *lang2) -> bool {
2913 if (!lang1 || !lang2)
2915 LanguageType lt1 = lang1->GetLanguageType();
2916 LanguageType lt2 = lang2->GetLanguageType();
2917 if (lt1 == guessed_language)
2918 return true; // make the selected frame's language come first
2919 if (lt2 == guessed_language)
2920 return false; // make the selected frame's language come first
2921 return (lt1 < lt2); // normal comparison otherwise
2926 bool is_first_language = true;
2928 for (Language *language : languages) {
2932 if (auto scavenger = language->GetTypeScavenger()) {
2933 Language::TypeScavenger::ResultSet search_results;
2934 if (scavenger->Find(best_scope, name_of_type, search_results) > 0) {
2935 for (const auto &search_result : search_results) {
2936 if (search_result && search_result->IsValid()) {
2938 search_result->DumpToStream(result.GetOutputStream(),
2939 this->m_command_options.m_show_help);
2944 // this is "type lookup SomeName" and we did find a match, so get out
2945 if (any_found && is_global_search)
2947 else if (is_first_language && is_global_search &&
2948 guessed_language != lldb::eLanguageTypeUnknown) {
2949 is_first_language = false;
2950 result.GetOutputStream().Printf(
2951 "no type was found in the current language %s matching '%s'; "
2952 "performing a global search across all languages\n",
2953 Language::GetNameForLanguageType(guessed_language), name_of_type);
2958 result.AppendMessageWithFormat("no type was found matching '%s'\n",
2961 result.SetStatus(any_found ? lldb::eReturnStatusSuccessFinishResult
2962 : lldb::eReturnStatusSuccessFinishNoResult);
2967 template <typename FormatterType>
2968 class CommandObjectFormatterInfo : public CommandObjectRaw {
2970 typedef std::function<typename FormatterType::SharedPointer(ValueObject &)>
2972 CommandObjectFormatterInfo(CommandInterpreter &interpreter,
2973 const char *formatter_name,
2974 DiscoveryFunction discovery_func)
2975 : CommandObjectRaw(interpreter, "", "", "",
2976 eCommandRequiresFrame),
2977 m_formatter_name(formatter_name ? formatter_name : ""),
2978 m_discovery_function(discovery_func) {
2980 name.Printf("type %s info", formatter_name);
2981 SetCommandName(name.GetString());
2983 help.Printf("This command evaluates the provided expression and shows "
2984 "which %s is applied to the resulting value (if any).",
2986 SetHelp(help.GetString());
2987 StreamString syntax;
2988 syntax.Printf("type %s info <expr>", formatter_name);
2989 SetSyntax(syntax.GetString());
2992 ~CommandObjectFormatterInfo() override = default;
2995 bool DoExecute(llvm::StringRef command,
2996 CommandReturnObject &result) override {
2997 TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget();
2998 Thread *thread = GetDefaultThread();
3000 result.AppendError("no default thread");
3001 result.SetStatus(lldb::eReturnStatusFailed);
3005 StackFrameSP frame_sp = thread->GetSelectedFrame();
3006 ValueObjectSP result_valobj_sp;
3007 EvaluateExpressionOptions options;
3008 lldb::ExpressionResults expr_result = target_sp->EvaluateExpression(
3009 command, frame_sp.get(), result_valobj_sp, options);
3010 if (expr_result == eExpressionCompleted && result_valobj_sp) {
3012 result_valobj_sp->GetQualifiedRepresentationIfAvailable(
3013 target_sp->GetPreferDynamicValue(),
3014 target_sp->GetEnableSyntheticValue());
3015 typename FormatterType::SharedPointer formatter_sp =
3016 m_discovery_function(*result_valobj_sp);
3018 std::string description(formatter_sp->GetDescription());
3019 result.GetOutputStream()
3020 << m_formatter_name << " applied to ("
3021 << result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>")
3022 << ") " << command << " is: " << description << "\n";
3023 result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
3025 result.GetOutputStream()
3026 << "no " << m_formatter_name << " applies to ("
3027 << result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>")
3028 << ") " << command << "\n";
3029 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
3033 result.AppendError("failed to evaluate expression");
3034 result.SetStatus(lldb::eReturnStatusFailed);
3040 std::string m_formatter_name;
3041 DiscoveryFunction m_discovery_function;
3044 class CommandObjectTypeFormat : public CommandObjectMultiword {
3046 CommandObjectTypeFormat(CommandInterpreter &interpreter)
3047 : CommandObjectMultiword(
3048 interpreter, "type format",
3049 "Commands for customizing value display formats.",
3050 "type format [<sub-command-options>] ") {
3052 "add", CommandObjectSP(new CommandObjectTypeFormatAdd(interpreter)));
3053 LoadSubCommand("clear", CommandObjectSP(
3054 new CommandObjectTypeFormatClear(interpreter)));
3055 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFormatDelete(
3058 "list", CommandObjectSP(new CommandObjectTypeFormatList(interpreter)));
3060 "info", CommandObjectSP(new CommandObjectFormatterInfo<TypeFormatImpl>(
3061 interpreter, "format",
3062 [](ValueObject &valobj) -> TypeFormatImpl::SharedPointer {
3063 return valobj.GetValueFormat();
3067 ~CommandObjectTypeFormat() override = default;
3070 #ifndef LLDB_DISABLE_PYTHON
3072 class CommandObjectTypeSynth : public CommandObjectMultiword {
3074 CommandObjectTypeSynth(CommandInterpreter &interpreter)
3075 : CommandObjectMultiword(
3076 interpreter, "type synthetic",
3077 "Commands for operating on synthetic type representations.",
3078 "type synthetic [<sub-command-options>] ") {
3079 LoadSubCommand("add",
3080 CommandObjectSP(new CommandObjectTypeSynthAdd(interpreter)));
3082 "clear", CommandObjectSP(new CommandObjectTypeSynthClear(interpreter)));
3083 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSynthDelete(
3086 "list", CommandObjectSP(new CommandObjectTypeSynthList(interpreter)));
3089 CommandObjectSP(new CommandObjectFormatterInfo<SyntheticChildren>(
3090 interpreter, "synthetic",
3091 [](ValueObject &valobj) -> SyntheticChildren::SharedPointer {
3092 return valobj.GetSyntheticChildren();
3096 ~CommandObjectTypeSynth() override = default;
3099 #endif // LLDB_DISABLE_PYTHON
3101 class CommandObjectTypeFilter : public CommandObjectMultiword {
3103 CommandObjectTypeFilter(CommandInterpreter &interpreter)
3104 : CommandObjectMultiword(interpreter, "type filter",
3105 "Commands for operating on type filters.",
3106 "type synthetic [<sub-command-options>] ") {
3108 "add", CommandObjectSP(new CommandObjectTypeFilterAdd(interpreter)));
3109 LoadSubCommand("clear", CommandObjectSP(
3110 new CommandObjectTypeFilterClear(interpreter)));
3111 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFilterDelete(
3114 "list", CommandObjectSP(new CommandObjectTypeFilterList(interpreter)));
3117 ~CommandObjectTypeFilter() override = default;
3120 class CommandObjectTypeCategory : public CommandObjectMultiword {
3122 CommandObjectTypeCategory(CommandInterpreter &interpreter)
3123 : CommandObjectMultiword(interpreter, "type category",
3124 "Commands for operating on type categories.",
3125 "type category [<sub-command-options>] ") {
3128 CommandObjectSP(new CommandObjectTypeCategoryDefine(interpreter)));
3131 CommandObjectSP(new CommandObjectTypeCategoryEnable(interpreter)));
3134 CommandObjectSP(new CommandObjectTypeCategoryDisable(interpreter)));
3137 CommandObjectSP(new CommandObjectTypeCategoryDelete(interpreter)));
3138 LoadSubCommand("list", CommandObjectSP(
3139 new CommandObjectTypeCategoryList(interpreter)));
3142 ~CommandObjectTypeCategory() override = default;
3145 class CommandObjectTypeSummary : public CommandObjectMultiword {
3147 CommandObjectTypeSummary(CommandInterpreter &interpreter)
3148 : CommandObjectMultiword(
3149 interpreter, "type summary",
3150 "Commands for editing variable summary display options.",
3151 "type summary [<sub-command-options>] ") {
3153 "add", CommandObjectSP(new CommandObjectTypeSummaryAdd(interpreter)));
3154 LoadSubCommand("clear", CommandObjectSP(new CommandObjectTypeSummaryClear(
3156 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSummaryDelete(
3159 "list", CommandObjectSP(new CommandObjectTypeSummaryList(interpreter)));
3161 "info", CommandObjectSP(new CommandObjectFormatterInfo<TypeSummaryImpl>(
3162 interpreter, "summary",
3163 [](ValueObject &valobj) -> TypeSummaryImpl::SharedPointer {
3164 return valobj.GetSummaryFormat();
3168 ~CommandObjectTypeSummary() override = default;
3171 //-------------------------------------------------------------------------
3172 // CommandObjectType
3173 //-------------------------------------------------------------------------
3175 CommandObjectType::CommandObjectType(CommandInterpreter &interpreter)
3176 : CommandObjectMultiword(interpreter, "type",
3177 "Commands for operating on the type system.",
3178 "type [<sub-command-options>]") {
3179 LoadSubCommand("category",
3180 CommandObjectSP(new CommandObjectTypeCategory(interpreter)));
3181 LoadSubCommand("filter",
3182 CommandObjectSP(new CommandObjectTypeFilter(interpreter)));
3183 LoadSubCommand("format",
3184 CommandObjectSP(new CommandObjectTypeFormat(interpreter)));
3185 LoadSubCommand("summary",
3186 CommandObjectSP(new CommandObjectTypeSummary(interpreter)));
3187 #ifndef LLDB_DISABLE_PYTHON
3188 LoadSubCommand("synthetic",
3189 CommandObjectSP(new CommandObjectTypeSynth(interpreter)));
3190 #endif // LLDB_DISABLE_PYTHON
3191 LoadSubCommand("lookup",
3192 CommandObjectSP(new CommandObjectTypeLookup(interpreter)));
3195 CommandObjectType::~CommandObjectType() = default;