[PowerPC] Collect some CallLowering arguments into a struct. [NFC]
[llvm-project.git] / lldb / source / Commands / CommandObjectType.cpp
blob87c107cfb94353b8e5c49ae28fddcb5e8dfb7c9d
1 //===-- CommandObjectType.cpp -----------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "CommandObjectType.h"
11 #include "lldb/Core/Debugger.h"
12 #include "lldb/Core/IOHandler.h"
13 #include "lldb/DataFormatters/DataVisualization.h"
14 #include "lldb/Host/Config.h"
15 #include "lldb/Host/OptionParser.h"
16 #include "lldb/Interpreter/CommandInterpreter.h"
17 #include "lldb/Interpreter/CommandObject.h"
18 #include "lldb/Interpreter/CommandReturnObject.h"
19 #include "lldb/Interpreter/OptionArgParser.h"
20 #include "lldb/Interpreter/OptionGroupFormat.h"
21 #include "lldb/Interpreter/OptionValueBoolean.h"
22 #include "lldb/Interpreter/OptionValueLanguage.h"
23 #include "lldb/Interpreter/OptionValueString.h"
24 #include "lldb/Interpreter/Options.h"
25 #include "lldb/Symbol/Symbol.h"
26 #include "lldb/Target/Language.h"
27 #include "lldb/Target/StackFrame.h"
28 #include "lldb/Target/Target.h"
29 #include "lldb/Target/Thread.h"
30 #include "lldb/Utility/ConstString.h"
31 #include "lldb/Utility/RegularExpression.h"
32 #include "lldb/Utility/StringList.h"
34 #include "llvm/ADT/STLExtras.h"
36 #include <algorithm>
37 #include <functional>
38 #include <memory>
40 using namespace lldb;
41 using namespace lldb_private;
43 class ScriptAddOptions {
44 public:
45 TypeSummaryImpl::Flags m_flags;
46 StringList m_target_types;
47 bool m_regex;
48 ConstString m_name;
49 std::string m_category;
51 ScriptAddOptions(const TypeSummaryImpl::Flags &flags, bool regx,
52 ConstString name, std::string catg)
53 : m_flags(flags), m_regex(regx), m_name(name), m_category(catg) {}
55 typedef std::shared_ptr<ScriptAddOptions> SharedPointer;
58 class SynthAddOptions {
59 public:
60 bool m_skip_pointers;
61 bool m_skip_references;
62 bool m_cascade;
63 bool m_regex;
64 StringList m_target_types;
65 std::string m_category;
67 SynthAddOptions(bool sptr, bool sref, bool casc, bool regx, std::string catg)
68 : m_skip_pointers(sptr), m_skip_references(sref), m_cascade(casc),
69 m_regex(regx), m_target_types(), m_category(catg) {}
71 typedef std::shared_ptr<SynthAddOptions> SharedPointer;
74 static bool WarnOnPotentialUnquotedUnsignedType(Args &command,
75 CommandReturnObject &result) {
76 if (command.empty())
77 return false;
79 for (auto entry : llvm::enumerate(command.entries().drop_back())) {
80 if (entry.value().ref() != "unsigned")
81 continue;
82 auto next = command.entries()[entry.index() + 1].ref();
83 if (next == "int" || next == "short" || next == "char" || next == "long") {
84 result.AppendWarningWithFormat(
85 "unsigned %s being treated as two types. if you meant the combined "
86 "type "
87 "name use quotes, as in \"unsigned %s\"\n",
88 next.str().c_str(), next.str().c_str());
89 return true;
92 return false;
95 #define LLDB_OPTIONS_type_summary_add
96 #include "CommandOptions.inc"
98 class CommandObjectTypeSummaryAdd : public CommandObjectParsed,
99 public IOHandlerDelegateMultiline {
100 private:
101 class CommandOptions : public Options {
102 public:
103 CommandOptions(CommandInterpreter &interpreter) : Options() {}
105 ~CommandOptions() override = default;
107 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
108 ExecutionContext *execution_context) override;
110 void OptionParsingStarting(ExecutionContext *execution_context) override;
112 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
113 return llvm::makeArrayRef(g_type_summary_add_options);
116 // Instance variables to hold the values for command options.
118 TypeSummaryImpl::Flags m_flags;
119 bool m_regex;
120 std::string m_format_string;
121 ConstString m_name;
122 std::string m_python_script;
123 std::string m_python_function;
124 bool m_is_add_script;
125 std::string m_category;
128 CommandOptions m_options;
130 Options *GetOptions() override { return &m_options; }
132 bool Execute_ScriptSummary(Args &command, CommandReturnObject &result);
134 bool Execute_StringSummary(Args &command, CommandReturnObject &result);
136 public:
137 enum SummaryFormatType { eRegularSummary, eRegexSummary, eNamedSummary };
139 CommandObjectTypeSummaryAdd(CommandInterpreter &interpreter);
141 ~CommandObjectTypeSummaryAdd() override = default;
143 void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
144 static const char *g_summary_addreader_instructions =
145 "Enter your Python command(s). Type 'DONE' to end.\n"
146 "def function (valobj,internal_dict):\n"
147 " \"\"\"valobj: an SBValue which you want to provide a summary "
148 "for\n"
149 " internal_dict: an LLDB support object not to be used\"\"\"\n";
151 StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
152 if (output_sp && interactive) {
153 output_sp->PutCString(g_summary_addreader_instructions);
154 output_sp->Flush();
158 void IOHandlerInputComplete(IOHandler &io_handler,
159 std::string &data) override {
160 StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
162 #if LLDB_ENABLE_PYTHON
163 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
164 if (interpreter) {
165 StringList lines;
166 lines.SplitIntoLines(data);
167 if (lines.GetSize() > 0) {
168 ScriptAddOptions *options_ptr =
169 ((ScriptAddOptions *)io_handler.GetUserData());
170 if (options_ptr) {
171 ScriptAddOptions::SharedPointer options(
172 options_ptr); // this will ensure that we get rid of the pointer
173 // when going out of scope
175 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
176 if (interpreter) {
177 std::string funct_name_str;
178 if (interpreter->GenerateTypeScriptFunction(lines,
179 funct_name_str)) {
180 if (funct_name_str.empty()) {
181 error_sp->Printf("unable to obtain a valid function name from "
182 "the script interpreter.\n");
183 error_sp->Flush();
184 } else {
185 // now I have a valid function name, let's add this as script
186 // for every type in the list
188 TypeSummaryImplSP script_format;
189 script_format = std::make_shared<ScriptSummaryFormat>(
190 options->m_flags, funct_name_str.c_str(),
191 lines.CopyList(" ").c_str());
193 Status error;
195 for (const std::string &type_name : options->m_target_types) {
196 CommandObjectTypeSummaryAdd::AddSummary(
197 ConstString(type_name), script_format,
198 (options->m_regex
199 ? CommandObjectTypeSummaryAdd::eRegexSummary
200 : CommandObjectTypeSummaryAdd::eRegularSummary),
201 options->m_category, &error);
202 if (error.Fail()) {
203 error_sp->Printf("error: %s", error.AsCString());
204 error_sp->Flush();
208 if (options->m_name) {
209 CommandObjectTypeSummaryAdd::AddSummary(
210 options->m_name, script_format,
211 CommandObjectTypeSummaryAdd::eNamedSummary,
212 options->m_category, &error);
213 if (error.Fail()) {
214 CommandObjectTypeSummaryAdd::AddSummary(
215 options->m_name, script_format,
216 CommandObjectTypeSummaryAdd::eNamedSummary,
217 options->m_category, &error);
218 if (error.Fail()) {
219 error_sp->Printf("error: %s", error.AsCString());
220 error_sp->Flush();
222 } else {
223 error_sp->Printf("error: %s", error.AsCString());
224 error_sp->Flush();
226 } else {
227 if (error.AsCString()) {
228 error_sp->Printf("error: %s", error.AsCString());
229 error_sp->Flush();
233 } else {
234 error_sp->Printf("error: unable to generate a function.\n");
235 error_sp->Flush();
237 } else {
238 error_sp->Printf("error: no script interpreter.\n");
239 error_sp->Flush();
241 } else {
242 error_sp->Printf("error: internal synchronization information "
243 "missing or invalid.\n");
244 error_sp->Flush();
246 } else {
247 error_sp->Printf("error: empty function, didn't add python command.\n");
248 error_sp->Flush();
250 } else {
251 error_sp->Printf(
252 "error: script interpreter missing, didn't add python command.\n");
253 error_sp->Flush();
255 #endif
256 io_handler.SetIsDone(true);
259 static bool AddSummary(ConstString type_name, lldb::TypeSummaryImplSP entry,
260 SummaryFormatType type, std::string category,
261 Status *error = nullptr);
263 protected:
264 bool DoExecute(Args &command, CommandReturnObject &result) override;
267 static const char *g_synth_addreader_instructions =
268 "Enter your Python command(s). Type 'DONE' to end.\n"
269 "You must define a Python class with these methods:\n"
270 " def __init__(self, valobj, dict):\n"
271 " def num_children(self):\n"
272 " def get_child_at_index(self, index):\n"
273 " def get_child_index(self, name):\n"
274 " def update(self):\n"
275 " '''Optional'''\n"
276 "class synthProvider:\n";
278 #define LLDB_OPTIONS_type_synth_add
279 #include "CommandOptions.inc"
281 class CommandObjectTypeSynthAdd : public CommandObjectParsed,
282 public IOHandlerDelegateMultiline {
283 private:
284 class CommandOptions : public Options {
285 public:
286 CommandOptions() : Options() {}
288 ~CommandOptions() override = default;
290 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
291 ExecutionContext *execution_context) override {
292 Status error;
293 const int short_option = m_getopt_table[option_idx].val;
294 bool success;
296 switch (short_option) {
297 case 'C':
298 m_cascade = OptionArgParser::ToBoolean(option_arg, true, &success);
299 if (!success)
300 error.SetErrorStringWithFormat("invalid value for cascade: %s",
301 option_arg.str().c_str());
302 break;
303 case 'P':
304 handwrite_python = true;
305 break;
306 case 'l':
307 m_class_name = std::string(option_arg);
308 is_class_based = true;
309 break;
310 case 'p':
311 m_skip_pointers = true;
312 break;
313 case 'r':
314 m_skip_references = true;
315 break;
316 case 'w':
317 m_category = std::string(option_arg);
318 break;
319 case 'x':
320 m_regex = true;
321 break;
322 default:
323 llvm_unreachable("Unimplemented option");
326 return error;
329 void OptionParsingStarting(ExecutionContext *execution_context) override {
330 m_cascade = true;
331 m_class_name = "";
332 m_skip_pointers = false;
333 m_skip_references = false;
334 m_category = "default";
335 is_class_based = false;
336 handwrite_python = false;
337 m_regex = false;
340 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
341 return llvm::makeArrayRef(g_type_synth_add_options);
344 // Instance variables to hold the values for command options.
346 bool m_cascade;
347 bool m_skip_references;
348 bool m_skip_pointers;
349 std::string m_class_name;
350 bool m_input_python;
351 std::string m_category;
352 bool is_class_based;
353 bool handwrite_python;
354 bool m_regex;
357 CommandOptions m_options;
359 Options *GetOptions() override { return &m_options; }
361 bool Execute_HandwritePython(Args &command, CommandReturnObject &result);
363 bool Execute_PythonClass(Args &command, CommandReturnObject &result);
365 protected:
366 bool DoExecute(Args &command, CommandReturnObject &result) override {
367 WarnOnPotentialUnquotedUnsignedType(command, result);
369 if (m_options.handwrite_python)
370 return Execute_HandwritePython(command, result);
371 else if (m_options.is_class_based)
372 return Execute_PythonClass(command, result);
373 else {
374 result.AppendError("must either provide a children list, a Python class "
375 "name, or use -P and type a Python class "
376 "line-by-line");
377 result.SetStatus(eReturnStatusFailed);
378 return false;
382 void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
383 StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
384 if (output_sp && interactive) {
385 output_sp->PutCString(g_synth_addreader_instructions);
386 output_sp->Flush();
390 void IOHandlerInputComplete(IOHandler &io_handler,
391 std::string &data) override {
392 StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
394 #if LLDB_ENABLE_PYTHON
395 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
396 if (interpreter) {
397 StringList lines;
398 lines.SplitIntoLines(data);
399 if (lines.GetSize() > 0) {
400 SynthAddOptions *options_ptr =
401 ((SynthAddOptions *)io_handler.GetUserData());
402 if (options_ptr) {
403 SynthAddOptions::SharedPointer options(
404 options_ptr); // this will ensure that we get rid of the pointer
405 // when going out of scope
407 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
408 if (interpreter) {
409 std::string class_name_str;
410 if (interpreter->GenerateTypeSynthClass(lines, class_name_str)) {
411 if (class_name_str.empty()) {
412 error_sp->Printf(
413 "error: unable to obtain a proper name for the class.\n");
414 error_sp->Flush();
415 } else {
416 // everything should be fine now, let's add the synth provider
417 // class
419 SyntheticChildrenSP synth_provider;
420 synth_provider = std::make_shared<ScriptedSyntheticChildren>(
421 SyntheticChildren::Flags()
422 .SetCascades(options->m_cascade)
423 .SetSkipPointers(options->m_skip_pointers)
424 .SetSkipReferences(options->m_skip_references),
425 class_name_str.c_str());
427 lldb::TypeCategoryImplSP category;
428 DataVisualization::Categories::GetCategory(
429 ConstString(options->m_category.c_str()), category);
431 Status error;
433 for (const std::string &type_name : options->m_target_types) {
434 if (!type_name.empty()) {
435 if (!CommandObjectTypeSynthAdd::AddSynth(
436 ConstString(type_name), synth_provider,
437 options->m_regex
438 ? CommandObjectTypeSynthAdd::eRegexSynth
439 : CommandObjectTypeSynthAdd::eRegularSynth,
440 options->m_category, &error)) {
441 error_sp->Printf("error: %s\n", error.AsCString());
442 error_sp->Flush();
443 break;
445 } else {
446 error_sp->Printf("error: invalid type name.\n");
447 error_sp->Flush();
448 break;
452 } else {
453 error_sp->Printf("error: unable to generate a class.\n");
454 error_sp->Flush();
456 } else {
457 error_sp->Printf("error: no script interpreter.\n");
458 error_sp->Flush();
460 } else {
461 error_sp->Printf("error: internal synchronization data missing.\n");
462 error_sp->Flush();
464 } else {
465 error_sp->Printf("error: empty function, didn't add python command.\n");
466 error_sp->Flush();
468 } else {
469 error_sp->Printf(
470 "error: script interpreter missing, didn't add python command.\n");
471 error_sp->Flush();
474 #endif
475 io_handler.SetIsDone(true);
478 public:
479 enum SynthFormatType { eRegularSynth, eRegexSynth };
481 CommandObjectTypeSynthAdd(CommandInterpreter &interpreter);
483 ~CommandObjectTypeSynthAdd() override = default;
485 static bool AddSynth(ConstString type_name, lldb::SyntheticChildrenSP entry,
486 SynthFormatType type, std::string category_name,
487 Status *error);
490 // CommandObjectTypeFormatAdd
492 #define LLDB_OPTIONS_type_format_add
493 #include "CommandOptions.inc"
495 class CommandObjectTypeFormatAdd : public CommandObjectParsed {
496 private:
497 class CommandOptions : public OptionGroup {
498 public:
499 CommandOptions() : OptionGroup() {}
501 ~CommandOptions() override = default;
503 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
504 return llvm::makeArrayRef(g_type_format_add_options);
507 void OptionParsingStarting(ExecutionContext *execution_context) override {
508 m_cascade = true;
509 m_skip_pointers = false;
510 m_skip_references = false;
511 m_regex = false;
512 m_category.assign("default");
513 m_custom_type_name.clear();
516 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
517 ExecutionContext *execution_context) override {
518 Status error;
519 const int short_option =
520 g_type_format_add_options[option_idx].short_option;
521 bool success;
523 switch (short_option) {
524 case 'C':
525 m_cascade = OptionArgParser::ToBoolean(option_value, true, &success);
526 if (!success)
527 error.SetErrorStringWithFormat("invalid value for cascade: %s",
528 option_value.str().c_str());
529 break;
530 case 'p':
531 m_skip_pointers = true;
532 break;
533 case 'w':
534 m_category.assign(option_value);
535 break;
536 case 'r':
537 m_skip_references = true;
538 break;
539 case 'x':
540 m_regex = true;
541 break;
542 case 't':
543 m_custom_type_name.assign(option_value);
544 break;
545 default:
546 llvm_unreachable("Unimplemented option");
549 return error;
552 // Instance variables to hold the values for command options.
554 bool m_cascade;
555 bool m_skip_references;
556 bool m_skip_pointers;
557 bool m_regex;
558 std::string m_category;
559 std::string m_custom_type_name;
562 OptionGroupOptions m_option_group;
563 OptionGroupFormat m_format_options;
564 CommandOptions m_command_options;
566 Options *GetOptions() override { return &m_option_group; }
568 public:
569 CommandObjectTypeFormatAdd(CommandInterpreter &interpreter)
570 : CommandObjectParsed(interpreter, "type format add",
571 "Add a new formatting style for a type.", nullptr),
572 m_option_group(), m_format_options(eFormatInvalid),
573 m_command_options() {
574 CommandArgumentEntry type_arg;
575 CommandArgumentData type_style_arg;
577 type_style_arg.arg_type = eArgTypeName;
578 type_style_arg.arg_repetition = eArgRepeatPlus;
580 type_arg.push_back(type_style_arg);
582 m_arguments.push_back(type_arg);
584 SetHelpLong(
586 The following examples of 'type format add' refer to this code snippet for context:
588 typedef int Aint;
589 typedef float Afloat;
590 typedef Aint Bint;
591 typedef Afloat Bfloat;
593 Aint ix = 5;
594 Bint iy = 5;
596 Afloat fx = 3.14;
597 BFloat fy = 3.14;
599 Adding default formatting:
601 (lldb) type format add -f hex AInt
602 (lldb) frame variable iy
605 " Produces hexadecimal display of iy, because no formatter is available for Bint and \
606 the one for Aint is used instead."
609 To prevent this use the cascade option '-C no' to prevent evaluation of typedef chains:
612 (lldb) type format add -f hex -C no AInt
614 Similar reasoning applies to this:
616 (lldb) type format add -f hex -C no float -p
619 " All float values and float references are now formatted as hexadecimal, but not \
620 pointers to floats. Nor will it change the default display for Afloat and Bfloat objects.");
622 // Add the "--format" to all options groups
623 m_option_group.Append(&m_format_options,
624 OptionGroupFormat::OPTION_GROUP_FORMAT,
625 LLDB_OPT_SET_1);
626 m_option_group.Append(&m_command_options);
627 m_option_group.Finalize();
630 ~CommandObjectTypeFormatAdd() override = default;
632 protected:
633 bool DoExecute(Args &command, CommandReturnObject &result) override {
634 const size_t argc = command.GetArgumentCount();
636 if (argc < 1) {
637 result.AppendErrorWithFormat("%s takes one or more args.\n",
638 m_cmd_name.c_str());
639 result.SetStatus(eReturnStatusFailed);
640 return false;
643 const Format format = m_format_options.GetFormat();
644 if (format == eFormatInvalid &&
645 m_command_options.m_custom_type_name.empty()) {
646 result.AppendErrorWithFormat("%s needs a valid format.\n",
647 m_cmd_name.c_str());
648 result.SetStatus(eReturnStatusFailed);
649 return false;
652 TypeFormatImplSP entry;
654 if (m_command_options.m_custom_type_name.empty())
655 entry = std::make_shared<TypeFormatImpl_Format>(
656 format, TypeFormatImpl::Flags()
657 .SetCascades(m_command_options.m_cascade)
658 .SetSkipPointers(m_command_options.m_skip_pointers)
659 .SetSkipReferences(m_command_options.m_skip_references));
660 else
661 entry = std::make_shared<TypeFormatImpl_EnumType>(
662 ConstString(m_command_options.m_custom_type_name.c_str()),
663 TypeFormatImpl::Flags()
664 .SetCascades(m_command_options.m_cascade)
665 .SetSkipPointers(m_command_options.m_skip_pointers)
666 .SetSkipReferences(m_command_options.m_skip_references));
668 // now I have a valid format, let's add it to every type
670 TypeCategoryImplSP category_sp;
671 DataVisualization::Categories::GetCategory(
672 ConstString(m_command_options.m_category), category_sp);
673 if (!category_sp)
674 return false;
676 WarnOnPotentialUnquotedUnsignedType(command, result);
678 for (auto &arg_entry : command.entries()) {
679 if (arg_entry.ref().empty()) {
680 result.AppendError("empty typenames not allowed");
681 result.SetStatus(eReturnStatusFailed);
682 return false;
685 ConstString typeCS(arg_entry.ref());
686 if (m_command_options.m_regex) {
687 RegularExpression typeRX(arg_entry.ref());
688 if (!typeRX.IsValid()) {
689 result.AppendError(
690 "regex format error (maybe this is not really a regex?)");
691 result.SetStatus(eReturnStatusFailed);
692 return false;
694 category_sp->GetRegexTypeSummariesContainer()->Delete(typeCS);
695 category_sp->GetRegexTypeFormatsContainer()->Add(std::move(typeRX),
696 entry);
697 } else
698 category_sp->GetTypeFormatsContainer()->Add(std::move(typeCS), entry);
701 result.SetStatus(eReturnStatusSuccessFinishNoResult);
702 return result.Succeeded();
706 #define LLDB_OPTIONS_type_formatter_delete
707 #include "CommandOptions.inc"
709 class CommandObjectTypeFormatterDelete : public CommandObjectParsed {
710 protected:
711 class CommandOptions : public Options {
712 public:
713 CommandOptions() : Options() {}
715 ~CommandOptions() override = default;
717 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
718 ExecutionContext *execution_context) override {
719 Status error;
720 const int short_option = m_getopt_table[option_idx].val;
722 switch (short_option) {
723 case 'a':
724 m_delete_all = true;
725 break;
726 case 'w':
727 m_category = std::string(option_arg);
728 break;
729 case 'l':
730 m_language = Language::GetLanguageTypeFromString(option_arg);
731 break;
732 default:
733 llvm_unreachable("Unimplemented option");
736 return error;
739 void OptionParsingStarting(ExecutionContext *execution_context) override {
740 m_delete_all = false;
741 m_category = "default";
742 m_language = lldb::eLanguageTypeUnknown;
745 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
746 return llvm::makeArrayRef(g_type_formatter_delete_options);
749 // Instance variables to hold the values for command options.
751 bool m_delete_all;
752 std::string m_category;
753 lldb::LanguageType m_language;
756 CommandOptions m_options;
757 uint32_t m_formatter_kind_mask;
759 Options *GetOptions() override { return &m_options; }
761 public:
762 CommandObjectTypeFormatterDelete(CommandInterpreter &interpreter,
763 uint32_t formatter_kind_mask,
764 const char *name, const char *help)
765 : CommandObjectParsed(interpreter, name, help, nullptr), m_options(),
766 m_formatter_kind_mask(formatter_kind_mask) {
767 CommandArgumentEntry type_arg;
768 CommandArgumentData type_style_arg;
770 type_style_arg.arg_type = eArgTypeName;
771 type_style_arg.arg_repetition = eArgRepeatPlain;
773 type_arg.push_back(type_style_arg);
775 m_arguments.push_back(type_arg);
778 ~CommandObjectTypeFormatterDelete() override = default;
780 protected:
781 virtual bool FormatterSpecificDeletion(ConstString typeCS) { return false; }
783 bool DoExecute(Args &command, CommandReturnObject &result) override {
784 const size_t argc = command.GetArgumentCount();
786 if (argc != 1) {
787 result.AppendErrorWithFormat("%s takes 1 arg.\n", m_cmd_name.c_str());
788 result.SetStatus(eReturnStatusFailed);
789 return false;
792 const char *typeA = command.GetArgumentAtIndex(0);
793 ConstString typeCS(typeA);
795 if (!typeCS) {
796 result.AppendError("empty typenames not allowed");
797 result.SetStatus(eReturnStatusFailed);
798 return false;
801 if (m_options.m_delete_all) {
802 DataVisualization::Categories::ForEach(
803 [this, typeCS](const lldb::TypeCategoryImplSP &category_sp) -> bool {
804 category_sp->Delete(typeCS, m_formatter_kind_mask);
805 return true;
807 result.SetStatus(eReturnStatusSuccessFinishNoResult);
808 return result.Succeeded();
811 bool delete_category = false;
812 bool extra_deletion = false;
814 if (m_options.m_language != lldb::eLanguageTypeUnknown) {
815 lldb::TypeCategoryImplSP category;
816 DataVisualization::Categories::GetCategory(m_options.m_language,
817 category);
818 if (category)
819 delete_category = category->Delete(typeCS, m_formatter_kind_mask);
820 extra_deletion = FormatterSpecificDeletion(typeCS);
821 } else {
822 lldb::TypeCategoryImplSP category;
823 DataVisualization::Categories::GetCategory(
824 ConstString(m_options.m_category.c_str()), category);
825 if (category)
826 delete_category = category->Delete(typeCS, m_formatter_kind_mask);
827 extra_deletion = FormatterSpecificDeletion(typeCS);
830 if (delete_category || extra_deletion) {
831 result.SetStatus(eReturnStatusSuccessFinishNoResult);
832 return result.Succeeded();
833 } else {
834 result.AppendErrorWithFormat("no custom formatter for %s.\n", typeA);
835 result.SetStatus(eReturnStatusFailed);
836 return false;
841 #define LLDB_OPTIONS_type_formatter_clear
842 #include "CommandOptions.inc"
844 class CommandObjectTypeFormatterClear : public CommandObjectParsed {
845 private:
846 class CommandOptions : public Options {
847 public:
848 CommandOptions() : Options() {}
850 ~CommandOptions() override = default;
852 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
853 ExecutionContext *execution_context) override {
854 Status error;
855 const int short_option = m_getopt_table[option_idx].val;
857 switch (short_option) {
858 case 'a':
859 m_delete_all = true;
860 break;
861 default:
862 llvm_unreachable("Unimplemented option");
865 return error;
868 void OptionParsingStarting(ExecutionContext *execution_context) override {
869 m_delete_all = false;
872 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
873 return llvm::makeArrayRef(g_type_formatter_clear_options);
876 // Instance variables to hold the values for command options.
877 bool m_delete_all;
880 CommandOptions m_options;
881 uint32_t m_formatter_kind_mask;
883 Options *GetOptions() override { return &m_options; }
885 public:
886 CommandObjectTypeFormatterClear(CommandInterpreter &interpreter,
887 uint32_t formatter_kind_mask,
888 const char *name, const char *help)
889 : CommandObjectParsed(interpreter, name, help, nullptr), m_options(),
890 m_formatter_kind_mask(formatter_kind_mask) {}
892 ~CommandObjectTypeFormatterClear() override = default;
894 protected:
895 virtual void FormatterSpecificDeletion() {}
897 bool DoExecute(Args &command, CommandReturnObject &result) override {
898 if (m_options.m_delete_all) {
899 DataVisualization::Categories::ForEach(
900 [this](const TypeCategoryImplSP &category_sp) -> bool {
901 category_sp->Clear(m_formatter_kind_mask);
902 return true;
904 } else {
905 lldb::TypeCategoryImplSP category;
906 if (command.GetArgumentCount() > 0) {
907 const char *cat_name = command.GetArgumentAtIndex(0);
908 ConstString cat_nameCS(cat_name);
909 DataVisualization::Categories::GetCategory(cat_nameCS, category);
910 } else {
911 DataVisualization::Categories::GetCategory(ConstString(nullptr),
912 category);
914 category->Clear(m_formatter_kind_mask);
917 FormatterSpecificDeletion();
919 result.SetStatus(eReturnStatusSuccessFinishResult);
920 return result.Succeeded();
924 // CommandObjectTypeFormatDelete
926 class CommandObjectTypeFormatDelete : public CommandObjectTypeFormatterDelete {
927 public:
928 CommandObjectTypeFormatDelete(CommandInterpreter &interpreter)
929 : CommandObjectTypeFormatterDelete(
930 interpreter,
931 eFormatCategoryItemValue | eFormatCategoryItemRegexValue,
932 "type format delete",
933 "Delete an existing formatting style for a type.") {}
935 ~CommandObjectTypeFormatDelete() override = default;
938 // CommandObjectTypeFormatClear
940 class CommandObjectTypeFormatClear : public CommandObjectTypeFormatterClear {
941 public:
942 CommandObjectTypeFormatClear(CommandInterpreter &interpreter)
943 : CommandObjectTypeFormatterClear(
944 interpreter,
945 eFormatCategoryItemValue | eFormatCategoryItemRegexValue,
946 "type format clear", "Delete all existing format styles.") {}
949 #define LLDB_OPTIONS_type_formatter_list
950 #include "CommandOptions.inc"
952 template <typename FormatterType>
953 class CommandObjectTypeFormatterList : public CommandObjectParsed {
954 typedef typename FormatterType::SharedPointer FormatterSharedPointer;
956 class CommandOptions : public Options {
957 public:
958 CommandOptions()
959 : Options(), m_category_regex("", ""),
960 m_category_language(lldb::eLanguageTypeUnknown,
961 lldb::eLanguageTypeUnknown) {}
963 ~CommandOptions() override = default;
965 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
966 ExecutionContext *execution_context) override {
967 Status error;
968 const int short_option = m_getopt_table[option_idx].val;
969 switch (short_option) {
970 case 'w':
971 m_category_regex.SetCurrentValue(option_arg);
972 m_category_regex.SetOptionWasSet();
973 break;
974 case 'l':
975 error = m_category_language.SetValueFromString(option_arg);
976 if (error.Success())
977 m_category_language.SetOptionWasSet();
978 break;
979 default:
980 llvm_unreachable("Unimplemented option");
983 return error;
986 void OptionParsingStarting(ExecutionContext *execution_context) override {
987 m_category_regex.Clear();
988 m_category_language.Clear();
991 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
992 return llvm::makeArrayRef(g_type_formatter_list_options);
995 // Instance variables to hold the values for command options.
997 OptionValueString m_category_regex;
998 OptionValueLanguage m_category_language;
1001 CommandOptions m_options;
1003 Options *GetOptions() override { return &m_options; }
1005 public:
1006 CommandObjectTypeFormatterList(CommandInterpreter &interpreter,
1007 const char *name, const char *help)
1008 : CommandObjectParsed(interpreter, name, help, nullptr), m_options() {
1009 CommandArgumentEntry type_arg;
1010 CommandArgumentData type_style_arg;
1012 type_style_arg.arg_type = eArgTypeName;
1013 type_style_arg.arg_repetition = eArgRepeatOptional;
1015 type_arg.push_back(type_style_arg);
1017 m_arguments.push_back(type_arg);
1020 ~CommandObjectTypeFormatterList() override = default;
1022 protected:
1023 virtual bool FormatterSpecificList(CommandReturnObject &result) {
1024 return false;
1027 bool DoExecute(Args &command, CommandReturnObject &result) override {
1028 const size_t argc = command.GetArgumentCount();
1030 std::unique_ptr<RegularExpression> category_regex;
1031 std::unique_ptr<RegularExpression> formatter_regex;
1033 if (m_options.m_category_regex.OptionWasSet()) {
1034 category_regex.reset(new RegularExpression(
1035 m_options.m_category_regex.GetCurrentValueAsRef()));
1036 if (!category_regex->IsValid()) {
1037 result.AppendErrorWithFormat(
1038 "syntax error in category regular expression '%s'",
1039 m_options.m_category_regex.GetCurrentValueAsRef().str().c_str());
1040 result.SetStatus(eReturnStatusFailed);
1041 return false;
1045 if (argc == 1) {
1046 const char *arg = command.GetArgumentAtIndex(0);
1047 formatter_regex.reset(
1048 new RegularExpression(llvm::StringRef::withNullAsEmpty(arg)));
1049 if (!formatter_regex->IsValid()) {
1050 result.AppendErrorWithFormat("syntax error in regular expression '%s'",
1051 arg);
1052 result.SetStatus(eReturnStatusFailed);
1053 return false;
1057 bool any_printed = false;
1059 auto category_closure =
1060 [&result, &formatter_regex,
1061 &any_printed](const lldb::TypeCategoryImplSP &category) -> void {
1062 result.GetOutputStream().Printf(
1063 "-----------------------\nCategory: %s%s\n-----------------------\n",
1064 category->GetName(), category->IsEnabled() ? "" : " (disabled)");
1066 TypeCategoryImpl::ForEachCallbacks<FormatterType> foreach;
1067 foreach
1068 .SetExact([&result, &formatter_regex, &any_printed](
1069 ConstString name,
1070 const FormatterSharedPointer &format_sp) -> bool {
1071 if (formatter_regex) {
1072 bool escape = true;
1073 if (name.GetStringRef() == formatter_regex->GetText()) {
1074 escape = false;
1075 } else if (formatter_regex->Execute(name.GetStringRef())) {
1076 escape = false;
1079 if (escape)
1080 return true;
1083 any_printed = true;
1084 result.GetOutputStream().Printf("%s: %s\n", name.AsCString(),
1085 format_sp->GetDescription().c_str());
1086 return true;
1089 foreach
1090 .SetWithRegex([&result, &formatter_regex, &any_printed](
1091 const RegularExpression &regex,
1092 const FormatterSharedPointer &format_sp) -> bool {
1093 if (formatter_regex) {
1094 bool escape = true;
1095 if (regex.GetText() == formatter_regex->GetText()) {
1096 escape = false;
1097 } else if (formatter_regex->Execute(regex.GetText())) {
1098 escape = false;
1101 if (escape)
1102 return true;
1105 any_printed = true;
1106 result.GetOutputStream().Printf("%s: %s\n",
1107 regex.GetText().str().c_str(),
1108 format_sp->GetDescription().c_str());
1109 return true;
1112 category->ForEach(foreach);
1115 if (m_options.m_category_language.OptionWasSet()) {
1116 lldb::TypeCategoryImplSP category_sp;
1117 DataVisualization::Categories::GetCategory(
1118 m_options.m_category_language.GetCurrentValue(), category_sp);
1119 if (category_sp)
1120 category_closure(category_sp);
1121 } else {
1122 DataVisualization::Categories::ForEach(
1123 [&category_regex, &category_closure](
1124 const lldb::TypeCategoryImplSP &category) -> bool {
1125 if (category_regex) {
1126 bool escape = true;
1127 if (category->GetName() == category_regex->GetText()) {
1128 escape = false;
1129 } else if (category_regex->Execute(
1130 llvm::StringRef::withNullAsEmpty(
1131 category->GetName()))) {
1132 escape = false;
1135 if (escape)
1136 return true;
1139 category_closure(category);
1141 return true;
1144 any_printed = FormatterSpecificList(result) | any_printed;
1147 if (any_printed)
1148 result.SetStatus(eReturnStatusSuccessFinishResult);
1149 else {
1150 result.GetOutputStream().PutCString("no matching results found.\n");
1151 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1153 return result.Succeeded();
1157 // CommandObjectTypeFormatList
1159 class CommandObjectTypeFormatList
1160 : public CommandObjectTypeFormatterList<TypeFormatImpl> {
1161 public:
1162 CommandObjectTypeFormatList(CommandInterpreter &interpreter)
1163 : CommandObjectTypeFormatterList(interpreter, "type format list",
1164 "Show a list of current formats.") {}
1167 Status CommandObjectTypeSummaryAdd::CommandOptions::SetOptionValue(
1168 uint32_t option_idx, llvm::StringRef option_arg,
1169 ExecutionContext *execution_context) {
1170 Status error;
1171 const int short_option = m_getopt_table[option_idx].val;
1172 bool success;
1174 switch (short_option) {
1175 case 'C':
1176 m_flags.SetCascades(OptionArgParser::ToBoolean(option_arg, true, &success));
1177 if (!success)
1178 error.SetErrorStringWithFormat("invalid value for cascade: %s",
1179 option_arg.str().c_str());
1180 break;
1181 case 'e':
1182 m_flags.SetDontShowChildren(false);
1183 break;
1184 case 'h':
1185 m_flags.SetHideEmptyAggregates(true);
1186 break;
1187 case 'v':
1188 m_flags.SetDontShowValue(true);
1189 break;
1190 case 'c':
1191 m_flags.SetShowMembersOneLiner(true);
1192 break;
1193 case 's':
1194 m_format_string = std::string(option_arg);
1195 break;
1196 case 'p':
1197 m_flags.SetSkipPointers(true);
1198 break;
1199 case 'r':
1200 m_flags.SetSkipReferences(true);
1201 break;
1202 case 'x':
1203 m_regex = true;
1204 break;
1205 case 'n':
1206 m_name.SetString(option_arg);
1207 break;
1208 case 'o':
1209 m_python_script = option_arg;
1210 m_is_add_script = true;
1211 break;
1212 case 'F':
1213 m_python_function = option_arg;
1214 m_is_add_script = true;
1215 break;
1216 case 'P':
1217 m_is_add_script = true;
1218 break;
1219 case 'w':
1220 m_category = std::string(option_arg);
1221 break;
1222 case 'O':
1223 m_flags.SetHideItemNames(true);
1224 break;
1225 default:
1226 llvm_unreachable("Unimplemented option");
1229 return error;
1232 void CommandObjectTypeSummaryAdd::CommandOptions::OptionParsingStarting(
1233 ExecutionContext *execution_context) {
1234 m_flags.Clear().SetCascades().SetDontShowChildren().SetDontShowValue(false);
1235 m_flags.SetShowMembersOneLiner(false)
1236 .SetSkipPointers(false)
1237 .SetSkipReferences(false)
1238 .SetHideItemNames(false);
1240 m_regex = false;
1241 m_name.Clear();
1242 m_python_script = "";
1243 m_python_function = "";
1244 m_format_string = "";
1245 m_is_add_script = false;
1246 m_category = "default";
1249 #if LLDB_ENABLE_PYTHON
1251 bool CommandObjectTypeSummaryAdd::Execute_ScriptSummary(
1252 Args &command, CommandReturnObject &result) {
1253 const size_t argc = command.GetArgumentCount();
1255 if (argc < 1 && !m_options.m_name) {
1256 result.AppendErrorWithFormat("%s takes one or more args.\n",
1257 m_cmd_name.c_str());
1258 result.SetStatus(eReturnStatusFailed);
1259 return false;
1262 TypeSummaryImplSP script_format;
1264 if (!m_options.m_python_function
1265 .empty()) // we have a Python function ready to use
1267 const char *funct_name = m_options.m_python_function.c_str();
1268 if (!funct_name || !funct_name[0]) {
1269 result.AppendError("function name empty.\n");
1270 result.SetStatus(eReturnStatusFailed);
1271 return false;
1274 std::string code =
1275 (" " + m_options.m_python_function + "(valobj,internal_dict)");
1277 script_format = std::make_shared<ScriptSummaryFormat>(
1278 m_options.m_flags, funct_name, code.c_str());
1280 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
1282 if (interpreter && !interpreter->CheckObjectExists(funct_name))
1283 result.AppendWarningWithFormat(
1284 "The provided function \"%s\" does not exist - "
1285 "please define it before attempting to use this summary.\n",
1286 funct_name);
1287 } else if (!m_options.m_python_script
1288 .empty()) // we have a quick 1-line script, just use it
1290 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
1291 if (!interpreter) {
1292 result.AppendError("script interpreter missing - unable to generate "
1293 "function wrapper.\n");
1294 result.SetStatus(eReturnStatusFailed);
1295 return false;
1297 StringList funct_sl;
1298 funct_sl << m_options.m_python_script.c_str();
1299 std::string funct_name_str;
1300 if (!interpreter->GenerateTypeScriptFunction(funct_sl, funct_name_str)) {
1301 result.AppendError("unable to generate function wrapper.\n");
1302 result.SetStatus(eReturnStatusFailed);
1303 return false;
1305 if (funct_name_str.empty()) {
1306 result.AppendError(
1307 "script interpreter failed to generate a valid function name.\n");
1308 result.SetStatus(eReturnStatusFailed);
1309 return false;
1312 std::string code = " " + m_options.m_python_script;
1314 script_format = std::make_shared<ScriptSummaryFormat>(
1315 m_options.m_flags, funct_name_str.c_str(), code.c_str());
1316 } else {
1317 // Use an IOHandler to grab Python code from the user
1318 ScriptAddOptions *options =
1319 new ScriptAddOptions(m_options.m_flags, m_options.m_regex,
1320 m_options.m_name, m_options.m_category);
1322 for (auto &entry : command.entries()) {
1323 if (entry.ref().empty()) {
1324 result.AppendError("empty typenames not allowed");
1325 result.SetStatus(eReturnStatusFailed);
1326 return false;
1329 options->m_target_types << entry.ref();
1332 m_interpreter.GetPythonCommandsFromIOHandler(
1333 " ", // Prompt
1334 *this, // IOHandlerDelegate
1335 options); // Baton for the "io_handler" that will be passed back into
1336 // our IOHandlerDelegate functions
1337 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1339 return result.Succeeded();
1342 // if I am here, script_format must point to something good, so I can add
1343 // that as a script summary to all interested parties
1345 Status error;
1347 for (auto &entry : command.entries()) {
1348 CommandObjectTypeSummaryAdd::AddSummary(
1349 ConstString(entry.ref()), script_format,
1350 (m_options.m_regex ? eRegexSummary : eRegularSummary),
1351 m_options.m_category, &error);
1352 if (error.Fail()) {
1353 result.AppendError(error.AsCString());
1354 result.SetStatus(eReturnStatusFailed);
1355 return false;
1359 if (m_options.m_name) {
1360 AddSummary(m_options.m_name, script_format, eNamedSummary,
1361 m_options.m_category, &error);
1362 if (error.Fail()) {
1363 result.AppendError(error.AsCString());
1364 result.AppendError("added to types, but not given a name");
1365 result.SetStatus(eReturnStatusFailed);
1366 return false;
1370 return result.Succeeded();
1373 #endif
1375 bool CommandObjectTypeSummaryAdd::Execute_StringSummary(
1376 Args &command, CommandReturnObject &result) {
1377 const size_t argc = command.GetArgumentCount();
1379 if (argc < 1 && !m_options.m_name) {
1380 result.AppendErrorWithFormat("%s takes one or more args.\n",
1381 m_cmd_name.c_str());
1382 result.SetStatus(eReturnStatusFailed);
1383 return false;
1386 if (!m_options.m_flags.GetShowMembersOneLiner() &&
1387 m_options.m_format_string.empty()) {
1388 result.AppendError("empty summary strings not allowed");
1389 result.SetStatus(eReturnStatusFailed);
1390 return false;
1393 const char *format_cstr = (m_options.m_flags.GetShowMembersOneLiner()
1394 ? ""
1395 : m_options.m_format_string.c_str());
1397 // ${var%S} is an endless recursion, prevent it
1398 if (strcmp(format_cstr, "${var%S}") == 0) {
1399 result.AppendError("recursive summary not allowed");
1400 result.SetStatus(eReturnStatusFailed);
1401 return false;
1404 std::unique_ptr<StringSummaryFormat> string_format(
1405 new StringSummaryFormat(m_options.m_flags, format_cstr));
1406 if (!string_format) {
1407 result.AppendError("summary creation failed");
1408 result.SetStatus(eReturnStatusFailed);
1409 return false;
1411 if (string_format->m_error.Fail()) {
1412 result.AppendErrorWithFormat("syntax error: %s",
1413 string_format->m_error.AsCString("<unknown>"));
1414 result.SetStatus(eReturnStatusFailed);
1415 return false;
1417 lldb::TypeSummaryImplSP entry(string_format.release());
1419 // now I have a valid format, let's add it to every type
1420 Status error;
1421 for (auto &arg_entry : command.entries()) {
1422 if (arg_entry.ref().empty()) {
1423 result.AppendError("empty typenames not allowed");
1424 result.SetStatus(eReturnStatusFailed);
1425 return false;
1427 ConstString typeCS(arg_entry.ref());
1429 AddSummary(typeCS, entry,
1430 (m_options.m_regex ? eRegexSummary : eRegularSummary),
1431 m_options.m_category, &error);
1433 if (error.Fail()) {
1434 result.AppendError(error.AsCString());
1435 result.SetStatus(eReturnStatusFailed);
1436 return false;
1440 if (m_options.m_name) {
1441 AddSummary(m_options.m_name, entry, eNamedSummary, m_options.m_category,
1442 &error);
1443 if (error.Fail()) {
1444 result.AppendError(error.AsCString());
1445 result.AppendError("added to types, but not given a name");
1446 result.SetStatus(eReturnStatusFailed);
1447 return false;
1451 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1452 return result.Succeeded();
1455 CommandObjectTypeSummaryAdd::CommandObjectTypeSummaryAdd(
1456 CommandInterpreter &interpreter)
1457 : CommandObjectParsed(interpreter, "type summary add",
1458 "Add a new summary style for a type.", nullptr),
1459 IOHandlerDelegateMultiline("DONE"), m_options(interpreter) {
1460 CommandArgumentEntry type_arg;
1461 CommandArgumentData type_style_arg;
1463 type_style_arg.arg_type = eArgTypeName;
1464 type_style_arg.arg_repetition = eArgRepeatPlus;
1466 type_arg.push_back(type_style_arg);
1468 m_arguments.push_back(type_arg);
1470 SetHelpLong(
1472 The following examples of 'type summary add' refer to this code snippet for context:
1474 struct JustADemo
1476 int* ptr;
1477 float value;
1478 JustADemo(int p = 1, float v = 0.1) : ptr(new int(p)), value(v) {}
1480 JustADemo demo_instance(42, 3.14);
1482 typedef JustADemo NewDemo;
1483 NewDemo new_demo_instance(42, 3.14);
1485 (lldb) type summary add --summary-string "the answer is ${*var.ptr}" JustADemo
1487 Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42"
1489 (lldb) type summary add --summary-string "the answer is ${*var.ptr}, and the question is ${var.value}" JustADemo
1491 Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42 and the question is 3.14"
1494 "Alternatively, you could define formatting for all pointers to integers and \
1495 rely on that when formatting JustADemo to obtain the same result:"
1498 (lldb) type summary add --summary-string "${var%V} -> ${*var}" "int *"
1499 (lldb) type summary add --summary-string "the answer is ${var.ptr}, and the question is ${var.value}" JustADemo
1502 "Type summaries are automatically applied to derived typedefs, so the examples \
1503 above apply to both JustADemo and NewDemo. The cascade option can be used to \
1504 suppress this behavior:"
1507 (lldb) type summary add --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo -C no
1509 The summary will now be used for values of JustADemo but not NewDemo.
1512 "By default summaries are shown for pointers and references to values of the \
1513 specified type. To suppress formatting for pointers use the -p option, or apply \
1514 the corresponding -r option to suppress formatting for references:"
1517 (lldb) type summary add -p -r --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo
1520 "One-line summaries including all fields in a type can be inferred without supplying an \
1521 explicit summary string by passing the -c option:"
1524 (lldb) type summary add -c JustADemo
1525 (lldb) frame variable demo_instance
1526 (ptr=<address>, value=3.14)
1529 "Type summaries normally suppress the nested display of individual fields. To \
1530 supply a summary to supplement the default structure add the -e option:"
1533 (lldb) type summary add -e --summary-string "*ptr = ${*var.ptr}" JustADemo
1536 "Now when displaying JustADemo values the int* is displayed, followed by the \
1537 standard LLDB sequence of children, one per line:"
1540 *ptr = 42 {
1541 ptr = <address>
1542 value = 3.14
1546 "You can also add summaries written in Python. These scripts use lldb public API to \
1547 gather information from your variables and produce a meaningful summary. To start a \
1548 multi-line script use the -P option. The function declaration will be displayed along with \
1549 a comment describing the two arguments. End your script with the word 'DONE' on a line by \
1550 itself:"
1553 (lldb) type summary add JustADemo -P
1554 def function (valobj,internal_dict):
1555 """valobj: an SBValue which you want to provide a summary for
1556 internal_dict: an LLDB support object not to be used"""
1557 value = valobj.GetChildMemberWithName('value');
1558 return 'My value is ' + value.GetValue();
1559 DONE
1561 Alternatively, the -o option can be used when providing a simple one-line Python script:
1563 (lldb) type summary add JustADemo -o "value = valobj.GetChildMemberWithName('value'); return 'My value is ' + value.GetValue();")");
1566 bool CommandObjectTypeSummaryAdd::DoExecute(Args &command,
1567 CommandReturnObject &result) {
1568 WarnOnPotentialUnquotedUnsignedType(command, result);
1570 if (m_options.m_is_add_script) {
1571 #if LLDB_ENABLE_PYTHON
1572 return Execute_ScriptSummary(command, result);
1573 #else
1574 result.AppendError("python is disabled");
1575 result.SetStatus(eReturnStatusFailed);
1576 return false;
1577 #endif
1580 return Execute_StringSummary(command, result);
1583 static bool FixArrayTypeNameWithRegex(ConstString &type_name) {
1584 llvm::StringRef type_name_ref(type_name.GetStringRef());
1586 if (type_name_ref.endswith("[]")) {
1587 std::string type_name_str(type_name.GetCString());
1588 type_name_str.resize(type_name_str.length() - 2);
1589 if (type_name_str.back() != ' ')
1590 type_name_str.append(" \\[[0-9]+\\]");
1591 else
1592 type_name_str.append("\\[[0-9]+\\]");
1593 type_name.SetCString(type_name_str.c_str());
1594 return true;
1596 return false;
1599 bool CommandObjectTypeSummaryAdd::AddSummary(ConstString type_name,
1600 TypeSummaryImplSP entry,
1601 SummaryFormatType type,
1602 std::string category_name,
1603 Status *error) {
1604 lldb::TypeCategoryImplSP category;
1605 DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()),
1606 category);
1608 if (type == eRegularSummary) {
1609 if (FixArrayTypeNameWithRegex(type_name))
1610 type = eRegexSummary;
1613 if (type == eRegexSummary) {
1614 RegularExpression typeRX(type_name.GetStringRef());
1615 if (!typeRX.IsValid()) {
1616 if (error)
1617 error->SetErrorString(
1618 "regex format error (maybe this is not really a regex?)");
1619 return false;
1622 category->GetRegexTypeSummariesContainer()->Delete(type_name);
1623 category->GetRegexTypeSummariesContainer()->Add(std::move(typeRX), entry);
1625 return true;
1626 } else if (type == eNamedSummary) {
1627 // system named summaries do not exist (yet?)
1628 DataVisualization::NamedSummaryFormats::Add(type_name, entry);
1629 return true;
1630 } else {
1631 category->GetTypeSummariesContainer()->Add(std::move(type_name), entry);
1632 return true;
1636 // CommandObjectTypeSummaryDelete
1638 class CommandObjectTypeSummaryDelete : public CommandObjectTypeFormatterDelete {
1639 public:
1640 CommandObjectTypeSummaryDelete(CommandInterpreter &interpreter)
1641 : CommandObjectTypeFormatterDelete(
1642 interpreter,
1643 eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary,
1644 "type summary delete", "Delete an existing summary for a type.") {}
1646 ~CommandObjectTypeSummaryDelete() override = default;
1648 protected:
1649 bool FormatterSpecificDeletion(ConstString typeCS) override {
1650 if (m_options.m_language != lldb::eLanguageTypeUnknown)
1651 return false;
1652 return DataVisualization::NamedSummaryFormats::Delete(typeCS);
1656 class CommandObjectTypeSummaryClear : public CommandObjectTypeFormatterClear {
1657 public:
1658 CommandObjectTypeSummaryClear(CommandInterpreter &interpreter)
1659 : CommandObjectTypeFormatterClear(
1660 interpreter,
1661 eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary,
1662 "type summary clear", "Delete all existing summaries.") {}
1664 protected:
1665 void FormatterSpecificDeletion() override {
1666 DataVisualization::NamedSummaryFormats::Clear();
1670 // CommandObjectTypeSummaryList
1672 class CommandObjectTypeSummaryList
1673 : public CommandObjectTypeFormatterList<TypeSummaryImpl> {
1674 public:
1675 CommandObjectTypeSummaryList(CommandInterpreter &interpreter)
1676 : CommandObjectTypeFormatterList(interpreter, "type summary list",
1677 "Show a list of current summaries.") {}
1679 protected:
1680 bool FormatterSpecificList(CommandReturnObject &result) override {
1681 if (DataVisualization::NamedSummaryFormats::GetCount() > 0) {
1682 result.GetOutputStream().Printf("Named summaries:\n");
1683 DataVisualization::NamedSummaryFormats::ForEach(
1684 [&result](ConstString name,
1685 const TypeSummaryImplSP &summary_sp) -> bool {
1686 result.GetOutputStream().Printf(
1687 "%s: %s\n", name.AsCString(),
1688 summary_sp->GetDescription().c_str());
1689 return true;
1691 return true;
1693 return false;
1697 // CommandObjectTypeCategoryDefine
1698 #define LLDB_OPTIONS_type_category_define
1699 #include "CommandOptions.inc"
1701 class CommandObjectTypeCategoryDefine : public CommandObjectParsed {
1702 class CommandOptions : public Options {
1703 public:
1704 CommandOptions()
1705 : Options(), m_define_enabled(false, false),
1706 m_cate_language(eLanguageTypeUnknown, eLanguageTypeUnknown) {}
1708 ~CommandOptions() override = default;
1710 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1711 ExecutionContext *execution_context) override {
1712 Status error;
1713 const int short_option = m_getopt_table[option_idx].val;
1715 switch (short_option) {
1716 case 'e':
1717 m_define_enabled.SetValueFromString(llvm::StringRef("true"));
1718 break;
1719 case 'l':
1720 error = m_cate_language.SetValueFromString(option_arg);
1721 break;
1722 default:
1723 llvm_unreachable("Unimplemented option");
1726 return error;
1729 void OptionParsingStarting(ExecutionContext *execution_context) override {
1730 m_define_enabled.Clear();
1731 m_cate_language.Clear();
1734 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1735 return llvm::makeArrayRef(g_type_category_define_options);
1738 // Instance variables to hold the values for command options.
1740 OptionValueBoolean m_define_enabled;
1741 OptionValueLanguage m_cate_language;
1744 CommandOptions m_options;
1746 Options *GetOptions() override { return &m_options; }
1748 public:
1749 CommandObjectTypeCategoryDefine(CommandInterpreter &interpreter)
1750 : CommandObjectParsed(interpreter, "type category define",
1751 "Define a new category as a source of formatters.",
1752 nullptr),
1753 m_options() {
1754 CommandArgumentEntry type_arg;
1755 CommandArgumentData type_style_arg;
1757 type_style_arg.arg_type = eArgTypeName;
1758 type_style_arg.arg_repetition = eArgRepeatPlus;
1760 type_arg.push_back(type_style_arg);
1762 m_arguments.push_back(type_arg);
1765 ~CommandObjectTypeCategoryDefine() override = default;
1767 protected:
1768 bool DoExecute(Args &command, CommandReturnObject &result) override {
1769 const size_t argc = command.GetArgumentCount();
1771 if (argc < 1) {
1772 result.AppendErrorWithFormat("%s takes 1 or more args.\n",
1773 m_cmd_name.c_str());
1774 result.SetStatus(eReturnStatusFailed);
1775 return false;
1778 for (auto &entry : command.entries()) {
1779 TypeCategoryImplSP category_sp;
1780 if (DataVisualization::Categories::GetCategory(ConstString(entry.ref()),
1781 category_sp) &&
1782 category_sp) {
1783 category_sp->AddLanguage(m_options.m_cate_language.GetCurrentValue());
1784 if (m_options.m_define_enabled.GetCurrentValue())
1785 DataVisualization::Categories::Enable(category_sp,
1786 TypeCategoryMap::Default);
1790 result.SetStatus(eReturnStatusSuccessFinishResult);
1791 return result.Succeeded();
1795 // CommandObjectTypeCategoryEnable
1796 #define LLDB_OPTIONS_type_category_enable
1797 #include "CommandOptions.inc"
1799 class CommandObjectTypeCategoryEnable : public CommandObjectParsed {
1800 class CommandOptions : public Options {
1801 public:
1802 CommandOptions() : Options() {}
1804 ~CommandOptions() override = default;
1806 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1807 ExecutionContext *execution_context) override {
1808 Status error;
1809 const int short_option = m_getopt_table[option_idx].val;
1811 switch (short_option) {
1812 case 'l':
1813 if (!option_arg.empty()) {
1814 m_language = Language::GetLanguageTypeFromString(option_arg);
1815 if (m_language == lldb::eLanguageTypeUnknown)
1816 error.SetErrorStringWithFormat("unrecognized language '%s'",
1817 option_arg.str().c_str());
1819 break;
1820 default:
1821 llvm_unreachable("Unimplemented option");
1824 return error;
1827 void OptionParsingStarting(ExecutionContext *execution_context) override {
1828 m_language = lldb::eLanguageTypeUnknown;
1831 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1832 return llvm::makeArrayRef(g_type_category_enable_options);
1835 // Instance variables to hold the values for command options.
1837 lldb::LanguageType m_language;
1840 CommandOptions m_options;
1842 Options *GetOptions() override { return &m_options; }
1844 public:
1845 CommandObjectTypeCategoryEnable(CommandInterpreter &interpreter)
1846 : CommandObjectParsed(interpreter, "type category enable",
1847 "Enable a category as a source of formatters.",
1848 nullptr),
1849 m_options() {
1850 CommandArgumentEntry type_arg;
1851 CommandArgumentData type_style_arg;
1853 type_style_arg.arg_type = eArgTypeName;
1854 type_style_arg.arg_repetition = eArgRepeatPlus;
1856 type_arg.push_back(type_style_arg);
1858 m_arguments.push_back(type_arg);
1861 ~CommandObjectTypeCategoryEnable() override = default;
1863 protected:
1864 bool DoExecute(Args &command, CommandReturnObject &result) override {
1865 const size_t argc = command.GetArgumentCount();
1867 if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) {
1868 result.AppendErrorWithFormat("%s takes arguments and/or a language",
1869 m_cmd_name.c_str());
1870 result.SetStatus(eReturnStatusFailed);
1871 return false;
1874 if (argc == 1 && strcmp(command.GetArgumentAtIndex(0), "*") == 0) {
1875 DataVisualization::Categories::EnableStar();
1876 } else if (argc > 0) {
1877 for (int i = argc - 1; i >= 0; i--) {
1878 const char *typeA = command.GetArgumentAtIndex(i);
1879 ConstString typeCS(typeA);
1881 if (!typeCS) {
1882 result.AppendError("empty category name not allowed");
1883 result.SetStatus(eReturnStatusFailed);
1884 return false;
1886 DataVisualization::Categories::Enable(typeCS);
1887 lldb::TypeCategoryImplSP cate;
1888 if (DataVisualization::Categories::GetCategory(typeCS, cate) && cate) {
1889 if (cate->GetCount() == 0) {
1890 result.AppendWarning("empty category enabled (typo?)");
1896 if (m_options.m_language != lldb::eLanguageTypeUnknown)
1897 DataVisualization::Categories::Enable(m_options.m_language);
1899 result.SetStatus(eReturnStatusSuccessFinishResult);
1900 return result.Succeeded();
1904 // CommandObjectTypeCategoryDelete
1906 class CommandObjectTypeCategoryDelete : public CommandObjectParsed {
1907 public:
1908 CommandObjectTypeCategoryDelete(CommandInterpreter &interpreter)
1909 : CommandObjectParsed(interpreter, "type category delete",
1910 "Delete a category and all associated formatters.",
1911 nullptr) {
1912 CommandArgumentEntry type_arg;
1913 CommandArgumentData type_style_arg;
1915 type_style_arg.arg_type = eArgTypeName;
1916 type_style_arg.arg_repetition = eArgRepeatPlus;
1918 type_arg.push_back(type_style_arg);
1920 m_arguments.push_back(type_arg);
1923 ~CommandObjectTypeCategoryDelete() override = default;
1925 protected:
1926 bool DoExecute(Args &command, CommandReturnObject &result) override {
1927 const size_t argc = command.GetArgumentCount();
1929 if (argc < 1) {
1930 result.AppendErrorWithFormat("%s takes 1 or more arg.\n",
1931 m_cmd_name.c_str());
1932 result.SetStatus(eReturnStatusFailed);
1933 return false;
1936 bool success = true;
1938 // the order is not relevant here
1939 for (int i = argc - 1; i >= 0; i--) {
1940 const char *typeA = command.GetArgumentAtIndex(i);
1941 ConstString typeCS(typeA);
1943 if (!typeCS) {
1944 result.AppendError("empty category name not allowed");
1945 result.SetStatus(eReturnStatusFailed);
1946 return false;
1948 if (!DataVisualization::Categories::Delete(typeCS))
1949 success = false; // keep deleting even if we hit an error
1951 if (success) {
1952 result.SetStatus(eReturnStatusSuccessFinishResult);
1953 return result.Succeeded();
1954 } else {
1955 result.AppendError("cannot delete one or more categories\n");
1956 result.SetStatus(eReturnStatusFailed);
1957 return false;
1962 // CommandObjectTypeCategoryDisable
1963 #define LLDB_OPTIONS_type_category_disable
1964 #include "CommandOptions.inc"
1966 class CommandObjectTypeCategoryDisable : public CommandObjectParsed {
1967 class CommandOptions : public Options {
1968 public:
1969 CommandOptions() : Options() {}
1971 ~CommandOptions() override = default;
1973 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1974 ExecutionContext *execution_context) override {
1975 Status error;
1976 const int short_option = m_getopt_table[option_idx].val;
1978 switch (short_option) {
1979 case 'l':
1980 if (!option_arg.empty()) {
1981 m_language = Language::GetLanguageTypeFromString(option_arg);
1982 if (m_language == lldb::eLanguageTypeUnknown)
1983 error.SetErrorStringWithFormat("unrecognized language '%s'",
1984 option_arg.str().c_str());
1986 break;
1987 default:
1988 llvm_unreachable("Unimplemented option");
1991 return error;
1994 void OptionParsingStarting(ExecutionContext *execution_context) override {
1995 m_language = lldb::eLanguageTypeUnknown;
1998 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1999 return llvm::makeArrayRef(g_type_category_disable_options);
2002 // Instance variables to hold the values for command options.
2004 lldb::LanguageType m_language;
2007 CommandOptions m_options;
2009 Options *GetOptions() override { return &m_options; }
2011 public:
2012 CommandObjectTypeCategoryDisable(CommandInterpreter &interpreter)
2013 : CommandObjectParsed(interpreter, "type category disable",
2014 "Disable a category as a source of formatters.",
2015 nullptr),
2016 m_options() {
2017 CommandArgumentEntry type_arg;
2018 CommandArgumentData type_style_arg;
2020 type_style_arg.arg_type = eArgTypeName;
2021 type_style_arg.arg_repetition = eArgRepeatPlus;
2023 type_arg.push_back(type_style_arg);
2025 m_arguments.push_back(type_arg);
2028 ~CommandObjectTypeCategoryDisable() override = default;
2030 protected:
2031 bool DoExecute(Args &command, CommandReturnObject &result) override {
2032 const size_t argc = command.GetArgumentCount();
2034 if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) {
2035 result.AppendErrorWithFormat("%s takes arguments and/or a language",
2036 m_cmd_name.c_str());
2037 result.SetStatus(eReturnStatusFailed);
2038 return false;
2041 if (argc == 1 && strcmp(command.GetArgumentAtIndex(0), "*") == 0) {
2042 DataVisualization::Categories::DisableStar();
2043 } else if (argc > 0) {
2044 // the order is not relevant here
2045 for (int i = argc - 1; i >= 0; i--) {
2046 const char *typeA = command.GetArgumentAtIndex(i);
2047 ConstString typeCS(typeA);
2049 if (!typeCS) {
2050 result.AppendError("empty category name not allowed");
2051 result.SetStatus(eReturnStatusFailed);
2052 return false;
2054 DataVisualization::Categories::Disable(typeCS);
2058 if (m_options.m_language != lldb::eLanguageTypeUnknown)
2059 DataVisualization::Categories::Disable(m_options.m_language);
2061 result.SetStatus(eReturnStatusSuccessFinishResult);
2062 return result.Succeeded();
2066 // CommandObjectTypeCategoryList
2068 class CommandObjectTypeCategoryList : public CommandObjectParsed {
2069 public:
2070 CommandObjectTypeCategoryList(CommandInterpreter &interpreter)
2071 : CommandObjectParsed(interpreter, "type category list",
2072 "Provide a list of all existing categories.",
2073 nullptr) {
2074 CommandArgumentEntry type_arg;
2075 CommandArgumentData type_style_arg;
2077 type_style_arg.arg_type = eArgTypeName;
2078 type_style_arg.arg_repetition = eArgRepeatOptional;
2080 type_arg.push_back(type_style_arg);
2082 m_arguments.push_back(type_arg);
2085 ~CommandObjectTypeCategoryList() override = default;
2087 protected:
2088 bool DoExecute(Args &command, CommandReturnObject &result) override {
2089 const size_t argc = command.GetArgumentCount();
2091 std::unique_ptr<RegularExpression> regex;
2093 if (argc == 1) {
2094 const char *arg = command.GetArgumentAtIndex(0);
2095 regex.reset(new RegularExpression(llvm::StringRef::withNullAsEmpty(arg)));
2096 if (!regex->IsValid()) {
2097 result.AppendErrorWithFormat(
2098 "syntax error in category regular expression '%s'", arg);
2099 result.SetStatus(eReturnStatusFailed);
2100 return false;
2102 } else if (argc != 0) {
2103 result.AppendErrorWithFormat("%s takes 0 or one arg.\n",
2104 m_cmd_name.c_str());
2105 result.SetStatus(eReturnStatusFailed);
2106 return false;
2109 DataVisualization::Categories::ForEach(
2110 [&regex, &result](const lldb::TypeCategoryImplSP &category_sp) -> bool {
2111 if (regex) {
2112 bool escape = true;
2113 if (regex->GetText() == category_sp->GetName()) {
2114 escape = false;
2115 } else if (regex->Execute(llvm::StringRef::withNullAsEmpty(
2116 category_sp->GetName()))) {
2117 escape = false;
2120 if (escape)
2121 return true;
2124 result.GetOutputStream().Printf(
2125 "Category: %s\n", category_sp->GetDescription().c_str());
2127 return true;
2130 result.SetStatus(eReturnStatusSuccessFinishResult);
2131 return result.Succeeded();
2135 // CommandObjectTypeFilterList
2137 class CommandObjectTypeFilterList
2138 : public CommandObjectTypeFormatterList<TypeFilterImpl> {
2139 public:
2140 CommandObjectTypeFilterList(CommandInterpreter &interpreter)
2141 : CommandObjectTypeFormatterList(interpreter, "type filter list",
2142 "Show a list of current filters.") {}
2145 #if LLDB_ENABLE_PYTHON
2147 // CommandObjectTypeSynthList
2149 class CommandObjectTypeSynthList
2150 : public CommandObjectTypeFormatterList<SyntheticChildren> {
2151 public:
2152 CommandObjectTypeSynthList(CommandInterpreter &interpreter)
2153 : CommandObjectTypeFormatterList(
2154 interpreter, "type synthetic list",
2155 "Show a list of current synthetic providers.") {}
2158 #endif
2160 // CommandObjectTypeFilterDelete
2162 class CommandObjectTypeFilterDelete : public CommandObjectTypeFormatterDelete {
2163 public:
2164 CommandObjectTypeFilterDelete(CommandInterpreter &interpreter)
2165 : CommandObjectTypeFormatterDelete(
2166 interpreter,
2167 eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter,
2168 "type filter delete", "Delete an existing filter for a type.") {}
2170 ~CommandObjectTypeFilterDelete() override = default;
2173 #if LLDB_ENABLE_PYTHON
2175 // CommandObjectTypeSynthDelete
2177 class CommandObjectTypeSynthDelete : public CommandObjectTypeFormatterDelete {
2178 public:
2179 CommandObjectTypeSynthDelete(CommandInterpreter &interpreter)
2180 : CommandObjectTypeFormatterDelete(
2181 interpreter,
2182 eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth,
2183 "type synthetic delete",
2184 "Delete an existing synthetic provider for a type.") {}
2186 ~CommandObjectTypeSynthDelete() override = default;
2189 #endif
2191 // CommandObjectTypeFilterClear
2193 class CommandObjectTypeFilterClear : public CommandObjectTypeFormatterClear {
2194 public:
2195 CommandObjectTypeFilterClear(CommandInterpreter &interpreter)
2196 : CommandObjectTypeFormatterClear(
2197 interpreter,
2198 eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter,
2199 "type filter clear", "Delete all existing filter.") {}
2202 #if LLDB_ENABLE_PYTHON
2203 // CommandObjectTypeSynthClear
2205 class CommandObjectTypeSynthClear : public CommandObjectTypeFormatterClear {
2206 public:
2207 CommandObjectTypeSynthClear(CommandInterpreter &interpreter)
2208 : CommandObjectTypeFormatterClear(
2209 interpreter,
2210 eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth,
2211 "type synthetic clear",
2212 "Delete all existing synthetic providers.") {}
2215 bool CommandObjectTypeSynthAdd::Execute_HandwritePython(
2216 Args &command, CommandReturnObject &result) {
2217 SynthAddOptions *options = new SynthAddOptions(
2218 m_options.m_skip_pointers, m_options.m_skip_references,
2219 m_options.m_cascade, m_options.m_regex, m_options.m_category);
2221 for (auto &entry : command.entries()) {
2222 if (entry.ref().empty()) {
2223 result.AppendError("empty typenames not allowed");
2224 result.SetStatus(eReturnStatusFailed);
2225 return false;
2228 options->m_target_types << entry.ref();
2231 m_interpreter.GetPythonCommandsFromIOHandler(
2232 " ", // Prompt
2233 *this, // IOHandlerDelegate
2234 options); // Baton for the "io_handler" that will be passed back into our
2235 // IOHandlerDelegate functions
2236 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2237 return result.Succeeded();
2240 bool CommandObjectTypeSynthAdd::Execute_PythonClass(
2241 Args &command, CommandReturnObject &result) {
2242 const size_t argc = command.GetArgumentCount();
2244 if (argc < 1) {
2245 result.AppendErrorWithFormat("%s takes one or more args.\n",
2246 m_cmd_name.c_str());
2247 result.SetStatus(eReturnStatusFailed);
2248 return false;
2251 if (m_options.m_class_name.empty() && !m_options.m_input_python) {
2252 result.AppendErrorWithFormat("%s needs either a Python class name or -P to "
2253 "directly input Python code.\n",
2254 m_cmd_name.c_str());
2255 result.SetStatus(eReturnStatusFailed);
2256 return false;
2259 SyntheticChildrenSP entry;
2261 ScriptedSyntheticChildren *impl = new ScriptedSyntheticChildren(
2262 SyntheticChildren::Flags()
2263 .SetCascades(m_options.m_cascade)
2264 .SetSkipPointers(m_options.m_skip_pointers)
2265 .SetSkipReferences(m_options.m_skip_references),
2266 m_options.m_class_name.c_str());
2268 entry.reset(impl);
2270 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
2272 if (interpreter &&
2273 !interpreter->CheckObjectExists(impl->GetPythonClassName()))
2274 result.AppendWarning("The provided class does not exist - please define it "
2275 "before attempting to use this synthetic provider");
2277 // now I have a valid provider, let's add it to every type
2279 lldb::TypeCategoryImplSP category;
2280 DataVisualization::Categories::GetCategory(
2281 ConstString(m_options.m_category.c_str()), category);
2283 Status error;
2285 for (auto &arg_entry : command.entries()) {
2286 if (arg_entry.ref().empty()) {
2287 result.AppendError("empty typenames not allowed");
2288 result.SetStatus(eReturnStatusFailed);
2289 return false;
2292 ConstString typeCS(arg_entry.ref());
2293 if (!AddSynth(typeCS, entry,
2294 m_options.m_regex ? eRegexSynth : eRegularSynth,
2295 m_options.m_category, &error)) {
2296 result.AppendError(error.AsCString());
2297 result.SetStatus(eReturnStatusFailed);
2298 return false;
2302 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2303 return result.Succeeded();
2306 CommandObjectTypeSynthAdd::CommandObjectTypeSynthAdd(
2307 CommandInterpreter &interpreter)
2308 : CommandObjectParsed(interpreter, "type synthetic add",
2309 "Add a new synthetic provider for a type.", nullptr),
2310 IOHandlerDelegateMultiline("DONE"), m_options() {
2311 CommandArgumentEntry type_arg;
2312 CommandArgumentData type_style_arg;
2314 type_style_arg.arg_type = eArgTypeName;
2315 type_style_arg.arg_repetition = eArgRepeatPlus;
2317 type_arg.push_back(type_style_arg);
2319 m_arguments.push_back(type_arg);
2322 bool CommandObjectTypeSynthAdd::AddSynth(ConstString type_name,
2323 SyntheticChildrenSP entry,
2324 SynthFormatType type,
2325 std::string category_name,
2326 Status *error) {
2327 lldb::TypeCategoryImplSP category;
2328 DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()),
2329 category);
2331 if (type == eRegularSynth) {
2332 if (FixArrayTypeNameWithRegex(type_name))
2333 type = eRegexSynth;
2336 if (category->AnyMatches(
2337 type_name, eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter,
2338 false)) {
2339 if (error)
2340 error->SetErrorStringWithFormat("cannot add synthetic for type %s when "
2341 "filter is defined in same category!",
2342 type_name.AsCString());
2343 return false;
2346 if (type == eRegexSynth) {
2347 RegularExpression typeRX(type_name.GetStringRef());
2348 if (!typeRX.IsValid()) {
2349 if (error)
2350 error->SetErrorString(
2351 "regex format error (maybe this is not really a regex?)");
2352 return false;
2355 category->GetRegexTypeSyntheticsContainer()->Delete(type_name);
2356 category->GetRegexTypeSyntheticsContainer()->Add(std::move(typeRX), entry);
2358 return true;
2359 } else {
2360 category->GetTypeSyntheticsContainer()->Add(std::move(type_name), entry);
2361 return true;
2365 #endif
2366 #define LLDB_OPTIONS_type_filter_add
2367 #include "CommandOptions.inc"
2369 class CommandObjectTypeFilterAdd : public CommandObjectParsed {
2370 private:
2371 class CommandOptions : public Options {
2372 typedef std::vector<std::string> option_vector;
2374 public:
2375 CommandOptions() : Options() {}
2377 ~CommandOptions() override = default;
2379 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2380 ExecutionContext *execution_context) override {
2381 Status error;
2382 const int short_option = m_getopt_table[option_idx].val;
2383 bool success;
2385 switch (short_option) {
2386 case 'C':
2387 m_cascade = OptionArgParser::ToBoolean(option_arg, true, &success);
2388 if (!success)
2389 error.SetErrorStringWithFormat("invalid value for cascade: %s",
2390 option_arg.str().c_str());
2391 break;
2392 case 'c':
2393 m_expr_paths.push_back(option_arg);
2394 has_child_list = true;
2395 break;
2396 case 'p':
2397 m_skip_pointers = true;
2398 break;
2399 case 'r':
2400 m_skip_references = true;
2401 break;
2402 case 'w':
2403 m_category = std::string(option_arg);
2404 break;
2405 case 'x':
2406 m_regex = true;
2407 break;
2408 default:
2409 llvm_unreachable("Unimplemented option");
2412 return error;
2415 void OptionParsingStarting(ExecutionContext *execution_context) override {
2416 m_cascade = true;
2417 m_skip_pointers = false;
2418 m_skip_references = false;
2419 m_category = "default";
2420 m_expr_paths.clear();
2421 has_child_list = false;
2422 m_regex = false;
2425 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2426 return llvm::makeArrayRef(g_type_filter_add_options);
2429 // Instance variables to hold the values for command options.
2431 bool m_cascade;
2432 bool m_skip_references;
2433 bool m_skip_pointers;
2434 bool m_input_python;
2435 option_vector m_expr_paths;
2436 std::string m_category;
2437 bool has_child_list;
2438 bool m_regex;
2440 typedef option_vector::iterator ExpressionPathsIterator;
2443 CommandOptions m_options;
2445 Options *GetOptions() override { return &m_options; }
2447 enum FilterFormatType { eRegularFilter, eRegexFilter };
2449 bool AddFilter(ConstString type_name, TypeFilterImplSP entry,
2450 FilterFormatType type, std::string category_name,
2451 Status *error) {
2452 lldb::TypeCategoryImplSP category;
2453 DataVisualization::Categories::GetCategory(
2454 ConstString(category_name.c_str()), category);
2456 if (type == eRegularFilter) {
2457 if (FixArrayTypeNameWithRegex(type_name))
2458 type = eRegexFilter;
2461 if (category->AnyMatches(
2462 type_name, eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth,
2463 false)) {
2464 if (error)
2465 error->SetErrorStringWithFormat("cannot add filter for type %s when "
2466 "synthetic is defined in same "
2467 "category!",
2468 type_name.AsCString());
2469 return false;
2472 if (type == eRegexFilter) {
2473 RegularExpression typeRX(type_name.GetStringRef());
2474 if (!typeRX.IsValid()) {
2475 if (error)
2476 error->SetErrorString(
2477 "regex format error (maybe this is not really a regex?)");
2478 return false;
2481 category->GetRegexTypeFiltersContainer()->Delete(type_name);
2482 category->GetRegexTypeFiltersContainer()->Add(std::move(typeRX), entry);
2484 return true;
2485 } else {
2486 category->GetTypeFiltersContainer()->Add(std::move(type_name), entry);
2487 return true;
2491 public:
2492 CommandObjectTypeFilterAdd(CommandInterpreter &interpreter)
2493 : CommandObjectParsed(interpreter, "type filter add",
2494 "Add a new filter for a type.", nullptr),
2495 m_options() {
2496 CommandArgumentEntry type_arg;
2497 CommandArgumentData type_style_arg;
2499 type_style_arg.arg_type = eArgTypeName;
2500 type_style_arg.arg_repetition = eArgRepeatPlus;
2502 type_arg.push_back(type_style_arg);
2504 m_arguments.push_back(type_arg);
2506 SetHelpLong(
2508 The following examples of 'type filter add' refer to this code snippet for context:
2510 class Foo {
2511 int a;
2512 int b;
2513 int c;
2514 int d;
2515 int e;
2516 int f;
2517 int g;
2518 int h;
2519 int i;
2521 Foo my_foo;
2523 Adding a simple filter:
2525 (lldb) type filter add --child a --child g Foo
2526 (lldb) frame variable my_foo
2529 "Produces output where only a and g are displayed. Other children of my_foo \
2530 (b, c, d, e, f, h and i) are available by asking for them explicitly:"
2533 (lldb) frame variable my_foo.b my_foo.c my_foo.i
2536 "The formatting option --raw on frame variable bypasses the filter, showing \
2537 all children of my_foo as if no filter was defined:"
2540 (lldb) frame variable my_foo --raw)");
2543 ~CommandObjectTypeFilterAdd() override = default;
2545 protected:
2546 bool DoExecute(Args &command, CommandReturnObject &result) override {
2547 const size_t argc = command.GetArgumentCount();
2549 if (argc < 1) {
2550 result.AppendErrorWithFormat("%s takes one or more args.\n",
2551 m_cmd_name.c_str());
2552 result.SetStatus(eReturnStatusFailed);
2553 return false;
2556 if (m_options.m_expr_paths.empty()) {
2557 result.AppendErrorWithFormat("%s needs one or more children.\n",
2558 m_cmd_name.c_str());
2559 result.SetStatus(eReturnStatusFailed);
2560 return false;
2563 TypeFilterImplSP entry(new TypeFilterImpl(
2564 SyntheticChildren::Flags()
2565 .SetCascades(m_options.m_cascade)
2566 .SetSkipPointers(m_options.m_skip_pointers)
2567 .SetSkipReferences(m_options.m_skip_references)));
2569 // go through the expression paths
2570 CommandOptions::ExpressionPathsIterator begin,
2571 end = m_options.m_expr_paths.end();
2573 for (begin = m_options.m_expr_paths.begin(); begin != end; begin++)
2574 entry->AddExpressionPath(*begin);
2576 // now I have a valid provider, let's add it to every type
2578 lldb::TypeCategoryImplSP category;
2579 DataVisualization::Categories::GetCategory(
2580 ConstString(m_options.m_category.c_str()), category);
2582 Status error;
2584 WarnOnPotentialUnquotedUnsignedType(command, result);
2586 for (auto &arg_entry : command.entries()) {
2587 if (arg_entry.ref().empty()) {
2588 result.AppendError("empty typenames not allowed");
2589 result.SetStatus(eReturnStatusFailed);
2590 return false;
2593 ConstString typeCS(arg_entry.ref());
2594 if (!AddFilter(typeCS, entry,
2595 m_options.m_regex ? eRegexFilter : eRegularFilter,
2596 m_options.m_category, &error)) {
2597 result.AppendError(error.AsCString());
2598 result.SetStatus(eReturnStatusFailed);
2599 return false;
2603 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2604 return result.Succeeded();
2608 // "type lookup"
2609 #define LLDB_OPTIONS_type_lookup
2610 #include "CommandOptions.inc"
2612 class CommandObjectTypeLookup : public CommandObjectRaw {
2613 protected:
2614 // this function is allowed to do a more aggressive job at guessing languages
2615 // than the expression parser is comfortable with - so leave the original
2616 // call alone and add one that is specific to type lookup
2617 lldb::LanguageType GuessLanguage(StackFrame *frame) {
2618 lldb::LanguageType lang_type = lldb::eLanguageTypeUnknown;
2620 if (!frame)
2621 return lang_type;
2623 lang_type = frame->GuessLanguage();
2624 if (lang_type != lldb::eLanguageTypeUnknown)
2625 return lang_type;
2627 Symbol *s = frame->GetSymbolContext(eSymbolContextSymbol).symbol;
2628 if (s)
2629 lang_type = s->GetMangled().GuessLanguage();
2631 return lang_type;
2634 class CommandOptions : public OptionGroup {
2635 public:
2636 CommandOptions()
2637 : OptionGroup(), m_show_help(false), m_language(eLanguageTypeUnknown) {}
2639 ~CommandOptions() override = default;
2641 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2642 return llvm::makeArrayRef(g_type_lookup_options);
2645 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
2646 ExecutionContext *execution_context) override {
2647 Status error;
2649 const int short_option = g_type_lookup_options[option_idx].short_option;
2651 switch (short_option) {
2652 case 'h':
2653 m_show_help = true;
2654 break;
2656 case 'l':
2657 m_language = Language::GetLanguageTypeFromString(option_value);
2658 break;
2660 default:
2661 llvm_unreachable("Unimplemented option");
2664 return error;
2667 void OptionParsingStarting(ExecutionContext *execution_context) override {
2668 m_show_help = false;
2669 m_language = eLanguageTypeUnknown;
2672 // Options table: Required for subclasses of Options.
2674 bool m_show_help;
2675 lldb::LanguageType m_language;
2678 OptionGroupOptions m_option_group;
2679 CommandOptions m_command_options;
2681 public:
2682 CommandObjectTypeLookup(CommandInterpreter &interpreter)
2683 : CommandObjectRaw(interpreter, "type lookup",
2684 "Lookup types and declarations in the current target, "
2685 "following language-specific naming conventions.",
2686 "type lookup <type-specifier>",
2687 eCommandRequiresTarget),
2688 m_option_group(), m_command_options() {
2689 m_option_group.Append(&m_command_options);
2690 m_option_group.Finalize();
2693 ~CommandObjectTypeLookup() override = default;
2695 Options *GetOptions() override { return &m_option_group; }
2697 llvm::StringRef GetHelpLong() override {
2698 if (!m_cmd_help_long.empty())
2699 return m_cmd_help_long;
2701 StreamString stream;
2702 Language::ForEach([&](Language *lang) {
2703 if (const char *help = lang->GetLanguageSpecificTypeLookupHelp())
2704 stream.Printf("%s\n", help);
2705 return true;
2708 m_cmd_help_long = stream.GetString();
2709 return m_cmd_help_long;
2712 bool DoExecute(llvm::StringRef raw_command_line,
2713 CommandReturnObject &result) override {
2714 if (raw_command_line.empty()) {
2715 result.SetError(
2716 "type lookup cannot be invoked without a type name as argument");
2717 return false;
2720 auto exe_ctx = GetCommandInterpreter().GetExecutionContext();
2721 m_option_group.NotifyOptionParsingStarting(&exe_ctx);
2723 OptionsWithRaw args(raw_command_line);
2724 const char *name_of_type = args.GetRawPart().c_str();
2726 if (args.HasArgs())
2727 if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group,
2728 exe_ctx))
2729 return false;
2731 ExecutionContextScope *best_scope = exe_ctx.GetBestExecutionContextScope();
2733 bool any_found = false;
2735 std::vector<Language *> languages;
2737 bool is_global_search = false;
2738 LanguageType guessed_language = lldb::eLanguageTypeUnknown;
2740 if ((is_global_search =
2741 (m_command_options.m_language == eLanguageTypeUnknown))) {
2742 Language::ForEach([&](Language *lang) {
2743 languages.push_back(lang);
2744 return true;
2746 } else {
2747 languages.push_back(Language::FindPlugin(m_command_options.m_language));
2750 // This is not the most efficient way to do this, but we support very few
2751 // languages so the cost of the sort is going to be dwarfed by the actual
2752 // lookup anyway
2753 if (StackFrame *frame = m_exe_ctx.GetFramePtr()) {
2754 guessed_language = GuessLanguage(frame);
2755 if (guessed_language != eLanguageTypeUnknown) {
2756 llvm::sort(
2757 languages.begin(), languages.end(),
2758 [guessed_language](Language *lang1, Language *lang2) -> bool {
2759 if (!lang1 || !lang2)
2760 return false;
2761 LanguageType lt1 = lang1->GetLanguageType();
2762 LanguageType lt2 = lang2->GetLanguageType();
2763 if (lt1 == guessed_language)
2764 return true; // make the selected frame's language come first
2765 if (lt2 == guessed_language)
2766 return false; // make the selected frame's language come first
2767 return (lt1 < lt2); // normal comparison otherwise
2772 bool is_first_language = true;
2774 for (Language *language : languages) {
2775 if (!language)
2776 continue;
2778 if (auto scavenger = language->GetTypeScavenger()) {
2779 Language::TypeScavenger::ResultSet search_results;
2780 if (scavenger->Find(best_scope, name_of_type, search_results) > 0) {
2781 for (const auto &search_result : search_results) {
2782 if (search_result && search_result->IsValid()) {
2783 any_found = true;
2784 search_result->DumpToStream(result.GetOutputStream(),
2785 this->m_command_options.m_show_help);
2790 // this is "type lookup SomeName" and we did find a match, so get out
2791 if (any_found && is_global_search)
2792 break;
2793 else if (is_first_language && is_global_search &&
2794 guessed_language != lldb::eLanguageTypeUnknown) {
2795 is_first_language = false;
2796 result.GetOutputStream().Printf(
2797 "no type was found in the current language %s matching '%s'; "
2798 "performing a global search across all languages\n",
2799 Language::GetNameForLanguageType(guessed_language), name_of_type);
2803 if (!any_found)
2804 result.AppendMessageWithFormat("no type was found matching '%s'\n",
2805 name_of_type);
2807 result.SetStatus(any_found ? lldb::eReturnStatusSuccessFinishResult
2808 : lldb::eReturnStatusSuccessFinishNoResult);
2809 return true;
2813 template <typename FormatterType>
2814 class CommandObjectFormatterInfo : public CommandObjectRaw {
2815 public:
2816 typedef std::function<typename FormatterType::SharedPointer(ValueObject &)>
2817 DiscoveryFunction;
2818 CommandObjectFormatterInfo(CommandInterpreter &interpreter,
2819 const char *formatter_name,
2820 DiscoveryFunction discovery_func)
2821 : CommandObjectRaw(interpreter, "", "", "", eCommandRequiresFrame),
2822 m_formatter_name(formatter_name ? formatter_name : ""),
2823 m_discovery_function(discovery_func) {
2824 StreamString name;
2825 name.Printf("type %s info", formatter_name);
2826 SetCommandName(name.GetString());
2827 StreamString help;
2828 help.Printf("This command evaluates the provided expression and shows "
2829 "which %s is applied to the resulting value (if any).",
2830 formatter_name);
2831 SetHelp(help.GetString());
2832 StreamString syntax;
2833 syntax.Printf("type %s info <expr>", formatter_name);
2834 SetSyntax(syntax.GetString());
2837 ~CommandObjectFormatterInfo() override = default;
2839 protected:
2840 bool DoExecute(llvm::StringRef command,
2841 CommandReturnObject &result) override {
2842 TargetSP target_sp = GetDebugger().GetSelectedTarget();
2843 Thread *thread = GetDefaultThread();
2844 if (!thread) {
2845 result.AppendError("no default thread");
2846 result.SetStatus(lldb::eReturnStatusFailed);
2847 return false;
2850 StackFrameSP frame_sp = thread->GetSelectedFrame();
2851 ValueObjectSP result_valobj_sp;
2852 EvaluateExpressionOptions options;
2853 lldb::ExpressionResults expr_result = target_sp->EvaluateExpression(
2854 command, frame_sp.get(), result_valobj_sp, options);
2855 if (expr_result == eExpressionCompleted && result_valobj_sp) {
2856 result_valobj_sp =
2857 result_valobj_sp->GetQualifiedRepresentationIfAvailable(
2858 target_sp->GetPreferDynamicValue(),
2859 target_sp->GetEnableSyntheticValue());
2860 typename FormatterType::SharedPointer formatter_sp =
2861 m_discovery_function(*result_valobj_sp);
2862 if (formatter_sp) {
2863 std::string description(formatter_sp->GetDescription());
2864 result.GetOutputStream()
2865 << m_formatter_name << " applied to ("
2866 << result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>")
2867 << ") " << command << " is: " << description << "\n";
2868 result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
2869 } else {
2870 result.GetOutputStream()
2871 << "no " << m_formatter_name << " applies to ("
2872 << result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>")
2873 << ") " << command << "\n";
2874 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
2876 return true;
2877 } else {
2878 result.AppendError("failed to evaluate expression");
2879 result.SetStatus(lldb::eReturnStatusFailed);
2880 return false;
2884 private:
2885 std::string m_formatter_name;
2886 DiscoveryFunction m_discovery_function;
2889 class CommandObjectTypeFormat : public CommandObjectMultiword {
2890 public:
2891 CommandObjectTypeFormat(CommandInterpreter &interpreter)
2892 : CommandObjectMultiword(
2893 interpreter, "type format",
2894 "Commands for customizing value display formats.",
2895 "type format [<sub-command-options>] ") {
2896 LoadSubCommand(
2897 "add", CommandObjectSP(new CommandObjectTypeFormatAdd(interpreter)));
2898 LoadSubCommand("clear", CommandObjectSP(
2899 new CommandObjectTypeFormatClear(interpreter)));
2900 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFormatDelete(
2901 interpreter)));
2902 LoadSubCommand(
2903 "list", CommandObjectSP(new CommandObjectTypeFormatList(interpreter)));
2904 LoadSubCommand(
2905 "info", CommandObjectSP(new CommandObjectFormatterInfo<TypeFormatImpl>(
2906 interpreter, "format",
2907 [](ValueObject &valobj) -> TypeFormatImpl::SharedPointer {
2908 return valobj.GetValueFormat();
2909 })));
2912 ~CommandObjectTypeFormat() override = default;
2915 #if LLDB_ENABLE_PYTHON
2917 class CommandObjectTypeSynth : public CommandObjectMultiword {
2918 public:
2919 CommandObjectTypeSynth(CommandInterpreter &interpreter)
2920 : CommandObjectMultiword(
2921 interpreter, "type synthetic",
2922 "Commands for operating on synthetic type representations.",
2923 "type synthetic [<sub-command-options>] ") {
2924 LoadSubCommand("add",
2925 CommandObjectSP(new CommandObjectTypeSynthAdd(interpreter)));
2926 LoadSubCommand(
2927 "clear", CommandObjectSP(new CommandObjectTypeSynthClear(interpreter)));
2928 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSynthDelete(
2929 interpreter)));
2930 LoadSubCommand(
2931 "list", CommandObjectSP(new CommandObjectTypeSynthList(interpreter)));
2932 LoadSubCommand(
2933 "info",
2934 CommandObjectSP(new CommandObjectFormatterInfo<SyntheticChildren>(
2935 interpreter, "synthetic",
2936 [](ValueObject &valobj) -> SyntheticChildren::SharedPointer {
2937 return valobj.GetSyntheticChildren();
2938 })));
2941 ~CommandObjectTypeSynth() override = default;
2944 #endif
2946 class CommandObjectTypeFilter : public CommandObjectMultiword {
2947 public:
2948 CommandObjectTypeFilter(CommandInterpreter &interpreter)
2949 : CommandObjectMultiword(interpreter, "type filter",
2950 "Commands for operating on type filters.",
2951 "type synthetic [<sub-command-options>] ") {
2952 LoadSubCommand(
2953 "add", CommandObjectSP(new CommandObjectTypeFilterAdd(interpreter)));
2954 LoadSubCommand("clear", CommandObjectSP(
2955 new CommandObjectTypeFilterClear(interpreter)));
2956 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFilterDelete(
2957 interpreter)));
2958 LoadSubCommand(
2959 "list", CommandObjectSP(new CommandObjectTypeFilterList(interpreter)));
2962 ~CommandObjectTypeFilter() override = default;
2965 class CommandObjectTypeCategory : public CommandObjectMultiword {
2966 public:
2967 CommandObjectTypeCategory(CommandInterpreter &interpreter)
2968 : CommandObjectMultiword(interpreter, "type category",
2969 "Commands for operating on type categories.",
2970 "type category [<sub-command-options>] ") {
2971 LoadSubCommand(
2972 "define",
2973 CommandObjectSP(new CommandObjectTypeCategoryDefine(interpreter)));
2974 LoadSubCommand(
2975 "enable",
2976 CommandObjectSP(new CommandObjectTypeCategoryEnable(interpreter)));
2977 LoadSubCommand(
2978 "disable",
2979 CommandObjectSP(new CommandObjectTypeCategoryDisable(interpreter)));
2980 LoadSubCommand(
2981 "delete",
2982 CommandObjectSP(new CommandObjectTypeCategoryDelete(interpreter)));
2983 LoadSubCommand("list", CommandObjectSP(
2984 new CommandObjectTypeCategoryList(interpreter)));
2987 ~CommandObjectTypeCategory() override = default;
2990 class CommandObjectTypeSummary : public CommandObjectMultiword {
2991 public:
2992 CommandObjectTypeSummary(CommandInterpreter &interpreter)
2993 : CommandObjectMultiword(
2994 interpreter, "type summary",
2995 "Commands for editing variable summary display options.",
2996 "type summary [<sub-command-options>] ") {
2997 LoadSubCommand(
2998 "add", CommandObjectSP(new CommandObjectTypeSummaryAdd(interpreter)));
2999 LoadSubCommand("clear", CommandObjectSP(new CommandObjectTypeSummaryClear(
3000 interpreter)));
3001 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSummaryDelete(
3002 interpreter)));
3003 LoadSubCommand(
3004 "list", CommandObjectSP(new CommandObjectTypeSummaryList(interpreter)));
3005 LoadSubCommand(
3006 "info", CommandObjectSP(new CommandObjectFormatterInfo<TypeSummaryImpl>(
3007 interpreter, "summary",
3008 [](ValueObject &valobj) -> TypeSummaryImpl::SharedPointer {
3009 return valobj.GetSummaryFormat();
3010 })));
3013 ~CommandObjectTypeSummary() override = default;
3016 // CommandObjectType
3018 CommandObjectType::CommandObjectType(CommandInterpreter &interpreter)
3019 : CommandObjectMultiword(interpreter, "type",
3020 "Commands for operating on the type system.",
3021 "type [<sub-command-options>]") {
3022 LoadSubCommand("category",
3023 CommandObjectSP(new CommandObjectTypeCategory(interpreter)));
3024 LoadSubCommand("filter",
3025 CommandObjectSP(new CommandObjectTypeFilter(interpreter)));
3026 LoadSubCommand("format",
3027 CommandObjectSP(new CommandObjectTypeFormat(interpreter)));
3028 LoadSubCommand("summary",
3029 CommandObjectSP(new CommandObjectTypeSummary(interpreter)));
3030 #if LLDB_ENABLE_PYTHON
3031 LoadSubCommand("synthetic",
3032 CommandObjectSP(new CommandObjectTypeSynth(interpreter)));
3033 #endif
3034 LoadSubCommand("lookup",
3035 CommandObjectSP(new CommandObjectTypeLookup(interpreter)));
3038 CommandObjectType::~CommandObjectType() = default;