1 //===-- CommandObjectType.cpp ---------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "CommandObjectType.h"
11 #include "lldb/Core/Debugger.h"
12 #include "lldb/Core/IOHandler.h"
13 #include "lldb/DataFormatters/DataVisualization.h"
14 #include "lldb/DataFormatters/FormatClasses.h"
15 #include "lldb/Host/Config.h"
16 #include "lldb/Host/OptionParser.h"
17 #include "lldb/Interpreter/CommandInterpreter.h"
18 #include "lldb/Interpreter/CommandObject.h"
19 #include "lldb/Interpreter/CommandOptionArgumentTable.h"
20 #include "lldb/Interpreter/CommandReturnObject.h"
21 #include "lldb/Interpreter/OptionArgParser.h"
22 #include "lldb/Interpreter/OptionGroupFormat.h"
23 #include "lldb/Interpreter/OptionValueBoolean.h"
24 #include "lldb/Interpreter/OptionValueLanguage.h"
25 #include "lldb/Interpreter/OptionValueString.h"
26 #include "lldb/Interpreter/Options.h"
27 #include "lldb/Symbol/Symbol.h"
28 #include "lldb/Target/Language.h"
29 #include "lldb/Target/StackFrame.h"
30 #include "lldb/Target/Target.h"
31 #include "lldb/Target/Thread.h"
32 #include "lldb/Utility/ConstString.h"
33 #include "lldb/Utility/RegularExpression.h"
34 #include "lldb/Utility/StringList.h"
36 #include "llvm/ADT/STLExtras.h"
43 using namespace lldb_private
;
45 class ScriptAddOptions
{
47 TypeSummaryImpl::Flags m_flags
;
48 StringList m_target_types
;
49 FormatterMatchType m_match_type
;
51 std::string m_category
;
53 ScriptAddOptions(const TypeSummaryImpl::Flags
&flags
,
54 FormatterMatchType match_type
, ConstString name
,
56 : m_flags(flags
), m_match_type(match_type
), m_name(name
),
59 typedef std::shared_ptr
<ScriptAddOptions
> SharedPointer
;
62 class SynthAddOptions
{
65 bool m_skip_references
;
67 FormatterMatchType m_match_type
;
68 StringList m_target_types
;
69 std::string m_category
;
71 SynthAddOptions(bool sptr
, bool sref
, bool casc
,
72 FormatterMatchType match_type
, std::string catg
)
73 : m_skip_pointers(sptr
), m_skip_references(sref
), m_cascade(casc
),
74 m_match_type(match_type
), m_category(catg
) {}
76 typedef std::shared_ptr
<SynthAddOptions
> SharedPointer
;
79 static bool WarnOnPotentialUnquotedUnsignedType(Args
&command
,
80 CommandReturnObject
&result
) {
84 for (auto entry
: llvm::enumerate(command
.entries().drop_back())) {
85 if (entry
.value().ref() != "unsigned")
87 auto next
= command
.entries()[entry
.index() + 1].ref();
88 if (next
== "int" || next
== "short" || next
== "char" || next
== "long") {
89 result
.AppendWarningWithFormat(
90 "unsigned %s being treated as two types. if you meant the combined "
92 "name use quotes, as in \"unsigned %s\"\n",
93 next
.str().c_str(), next
.str().c_str());
100 const char *FormatCategoryToString(FormatCategoryItem item
, bool long_name
) {
102 case eFormatCategoryItemSummary
:
104 case eFormatCategoryItemFilter
:
106 case eFormatCategoryItemSynth
:
108 return "synthetic child provider";
110 case eFormatCategoryItemFormat
:
113 llvm_unreachable("Fully covered switch above!");
116 #define LLDB_OPTIONS_type_summary_add
117 #include "CommandOptions.inc"
119 class CommandObjectTypeSummaryAdd
: public CommandObjectParsed
,
120 public IOHandlerDelegateMultiline
{
122 class CommandOptions
: public Options
{
124 CommandOptions(CommandInterpreter
&interpreter
) {}
126 ~CommandOptions() override
= default;
128 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
129 ExecutionContext
*execution_context
) override
;
131 void OptionParsingStarting(ExecutionContext
*execution_context
) override
;
133 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
134 return llvm::ArrayRef(g_type_summary_add_options
);
137 // Instance variables to hold the values for command options.
139 TypeSummaryImpl::Flags m_flags
;
140 FormatterMatchType m_match_type
= eFormatterMatchExact
;
141 std::string m_format_string
;
143 std::string m_python_script
;
144 std::string m_python_function
;
145 bool m_is_add_script
= false;
146 std::string m_category
;
149 CommandOptions m_options
;
151 Options
*GetOptions() override
{ return &m_options
; }
153 bool Execute_ScriptSummary(Args
&command
, CommandReturnObject
&result
);
155 bool Execute_StringSummary(Args
&command
, CommandReturnObject
&result
);
158 CommandObjectTypeSummaryAdd(CommandInterpreter
&interpreter
);
160 ~CommandObjectTypeSummaryAdd() override
= default;
162 void IOHandlerActivated(IOHandler
&io_handler
, bool interactive
) override
{
163 static const char *g_summary_addreader_instructions
=
164 "Enter your Python command(s). Type 'DONE' to end.\n"
165 "def function (valobj,internal_dict):\n"
166 " \"\"\"valobj: an SBValue which you want to provide a summary "
168 " internal_dict: an LLDB support object not to be used\"\"\"\n";
170 StreamFileSP
output_sp(io_handler
.GetOutputStreamFileSP());
171 if (output_sp
&& interactive
) {
172 output_sp
->PutCString(g_summary_addreader_instructions
);
177 void IOHandlerInputComplete(IOHandler
&io_handler
,
178 std::string
&data
) override
{
179 StreamFileSP error_sp
= io_handler
.GetErrorStreamFileSP();
181 #if LLDB_ENABLE_PYTHON
182 ScriptInterpreter
*interpreter
= GetDebugger().GetScriptInterpreter();
185 lines
.SplitIntoLines(data
);
186 if (lines
.GetSize() > 0) {
187 ScriptAddOptions
*options_ptr
=
188 ((ScriptAddOptions
*)io_handler
.GetUserData());
190 ScriptAddOptions::SharedPointer
options(
191 options_ptr
); // this will ensure that we get rid of the pointer
192 // when going out of scope
194 ScriptInterpreter
*interpreter
= GetDebugger().GetScriptInterpreter();
196 std::string funct_name_str
;
197 if (interpreter
->GenerateTypeScriptFunction(lines
,
199 if (funct_name_str
.empty()) {
200 error_sp
->Printf("unable to obtain a valid function name from "
201 "the script interpreter.\n");
204 // now I have a valid function name, let's add this as script
205 // for every type in the list
207 TypeSummaryImplSP script_format
;
208 script_format
= std::make_shared
<ScriptSummaryFormat
>(
209 options
->m_flags
, funct_name_str
.c_str(),
210 lines
.CopyList(" ").c_str());
214 for (const std::string
&type_name
: options
->m_target_types
) {
215 AddSummary(ConstString(type_name
), script_format
,
216 options
->m_match_type
, options
->m_category
,
219 error_sp
->Printf("error: %s", error
.AsCString());
224 if (options
->m_name
) {
225 CommandObjectTypeSummaryAdd::AddNamedSummary(
226 options
->m_name
, script_format
, &error
);
228 CommandObjectTypeSummaryAdd::AddNamedSummary(
229 options
->m_name
, script_format
, &error
);
231 error_sp
->Printf("error: %s", error
.AsCString());
235 error_sp
->Printf("error: %s", error
.AsCString());
239 if (error
.AsCString()) {
240 error_sp
->Printf("error: %s", error
.AsCString());
246 error_sp
->Printf("error: unable to generate a function.\n");
250 error_sp
->Printf("error: no script interpreter.\n");
254 error_sp
->Printf("error: internal synchronization information "
255 "missing or invalid.\n");
259 error_sp
->Printf("error: empty function, didn't add python command.\n");
264 "error: script interpreter missing, didn't add python command.\n");
268 io_handler
.SetIsDone(true);
271 bool AddSummary(ConstString type_name
, lldb::TypeSummaryImplSP entry
,
272 FormatterMatchType match_type
, std::string category
,
273 Status
*error
= nullptr);
275 bool AddNamedSummary(ConstString summary_name
, lldb::TypeSummaryImplSP entry
,
276 Status
*error
= nullptr);
279 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
;
282 static const char *g_synth_addreader_instructions
=
283 "Enter your Python command(s). Type 'DONE' to end.\n"
284 "You must define a Python class with these methods:\n"
285 " def __init__(self, valobj, internal_dict):\n"
286 " def num_children(self):\n"
287 " def get_child_at_index(self, index):\n"
288 " def get_child_index(self, name):\n"
289 " def update(self):\n"
291 "class synthProvider:\n";
293 #define LLDB_OPTIONS_type_synth_add
294 #include "CommandOptions.inc"
296 class CommandObjectTypeSynthAdd
: public CommandObjectParsed
,
297 public IOHandlerDelegateMultiline
{
299 class CommandOptions
: public Options
{
301 CommandOptions() = default;
303 ~CommandOptions() override
= default;
305 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
306 ExecutionContext
*execution_context
) override
{
308 const int short_option
= m_getopt_table
[option_idx
].val
;
311 switch (short_option
) {
313 m_cascade
= OptionArgParser::ToBoolean(option_arg
, true, &success
);
315 error
= Status::FromErrorStringWithFormat(
316 "invalid value for cascade: %s", option_arg
.str().c_str());
319 handwrite_python
= true;
322 m_class_name
= std::string(option_arg
);
323 is_class_based
= true;
326 m_skip_pointers
= true;
329 m_skip_references
= true;
332 m_category
= std::string(option_arg
);
335 if (m_match_type
== eFormatterMatchCallback
)
336 error
= Status::FromErrorString(
337 "can't use --regex and --recognizer-function at the same time");
339 m_match_type
= eFormatterMatchRegex
;
342 if (m_match_type
== eFormatterMatchRegex
)
343 error
= Status::FromErrorString(
344 "can't use --regex and --recognizer-function at the same time");
346 m_match_type
= eFormatterMatchCallback
;
349 llvm_unreachable("Unimplemented option");
355 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
358 m_skip_pointers
= false;
359 m_skip_references
= false;
360 m_category
= "default";
361 is_class_based
= false;
362 handwrite_python
= false;
363 m_match_type
= eFormatterMatchExact
;
366 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
367 return llvm::ArrayRef(g_type_synth_add_options
);
370 // Instance variables to hold the values for command options.
373 bool m_skip_references
;
374 bool m_skip_pointers
;
375 std::string m_class_name
;
377 std::string m_category
;
379 bool handwrite_python
;
380 FormatterMatchType m_match_type
;
383 CommandOptions m_options
;
385 Options
*GetOptions() override
{ return &m_options
; }
387 bool Execute_HandwritePython(Args
&command
, CommandReturnObject
&result
);
389 bool Execute_PythonClass(Args
&command
, CommandReturnObject
&result
);
392 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
393 WarnOnPotentialUnquotedUnsignedType(command
, result
);
395 if (m_options
.handwrite_python
)
396 Execute_HandwritePython(command
, result
);
397 else if (m_options
.is_class_based
)
398 Execute_PythonClass(command
, result
);
400 result
.AppendError("must either provide a children list, a Python class "
401 "name, or use -P and type a Python class "
406 void IOHandlerActivated(IOHandler
&io_handler
, bool interactive
) override
{
407 StreamFileSP
output_sp(io_handler
.GetOutputStreamFileSP());
408 if (output_sp
&& interactive
) {
409 output_sp
->PutCString(g_synth_addreader_instructions
);
414 void IOHandlerInputComplete(IOHandler
&io_handler
,
415 std::string
&data
) override
{
416 StreamFileSP error_sp
= io_handler
.GetErrorStreamFileSP();
418 #if LLDB_ENABLE_PYTHON
419 ScriptInterpreter
*interpreter
= GetDebugger().GetScriptInterpreter();
422 lines
.SplitIntoLines(data
);
423 if (lines
.GetSize() > 0) {
424 SynthAddOptions
*options_ptr
=
425 ((SynthAddOptions
*)io_handler
.GetUserData());
427 SynthAddOptions::SharedPointer
options(
428 options_ptr
); // this will ensure that we get rid of the pointer
429 // when going out of scope
431 ScriptInterpreter
*interpreter
= GetDebugger().GetScriptInterpreter();
433 std::string class_name_str
;
434 if (interpreter
->GenerateTypeSynthClass(lines
, class_name_str
)) {
435 if (class_name_str
.empty()) {
437 "error: unable to obtain a proper name for the class.\n");
440 // everything should be fine now, let's add the synth provider
443 SyntheticChildrenSP synth_provider
;
444 synth_provider
= std::make_shared
<ScriptedSyntheticChildren
>(
445 SyntheticChildren::Flags()
446 .SetCascades(options
->m_cascade
)
447 .SetSkipPointers(options
->m_skip_pointers
)
448 .SetSkipReferences(options
->m_skip_references
),
449 class_name_str
.c_str());
451 lldb::TypeCategoryImplSP category
;
452 DataVisualization::Categories::GetCategory(
453 ConstString(options
->m_category
.c_str()), category
);
457 for (const std::string
&type_name
: options
->m_target_types
) {
458 if (!type_name
.empty()) {
459 if (AddSynth(ConstString(type_name
), synth_provider
,
460 options
->m_match_type
, options
->m_category
,
462 error_sp
->Printf("error: %s\n", error
.AsCString());
467 error_sp
->Printf("error: invalid type name.\n");
474 error_sp
->Printf("error: unable to generate a class.\n");
478 error_sp
->Printf("error: no script interpreter.\n");
482 error_sp
->Printf("error: internal synchronization data missing.\n");
486 error_sp
->Printf("error: empty function, didn't add python command.\n");
491 "error: script interpreter missing, didn't add python command.\n");
496 io_handler
.SetIsDone(true);
500 CommandObjectTypeSynthAdd(CommandInterpreter
&interpreter
);
502 ~CommandObjectTypeSynthAdd() override
= default;
504 bool AddSynth(ConstString type_name
, lldb::SyntheticChildrenSP entry
,
505 FormatterMatchType match_type
, std::string category_name
,
509 // CommandObjectTypeFormatAdd
511 #define LLDB_OPTIONS_type_format_add
512 #include "CommandOptions.inc"
514 class CommandObjectTypeFormatAdd
: public CommandObjectParsed
{
516 class CommandOptions
: public OptionGroup
{
518 CommandOptions() = default;
520 ~CommandOptions() override
= default;
522 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
523 return llvm::ArrayRef(g_type_format_add_options
);
526 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
528 m_skip_pointers
= false;
529 m_skip_references
= false;
531 m_category
.assign("default");
532 m_custom_type_name
.clear();
535 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_value
,
536 ExecutionContext
*execution_context
) override
{
538 const int short_option
=
539 g_type_format_add_options
[option_idx
].short_option
;
542 switch (short_option
) {
544 m_cascade
= OptionArgParser::ToBoolean(option_value
, true, &success
);
546 error
= Status::FromErrorStringWithFormat(
547 "invalid value for cascade: %s", option_value
.str().c_str());
550 m_skip_pointers
= true;
553 m_category
.assign(std::string(option_value
));
556 m_skip_references
= true;
562 m_custom_type_name
.assign(std::string(option_value
));
565 llvm_unreachable("Unimplemented option");
571 // Instance variables to hold the values for command options.
574 bool m_skip_references
;
575 bool m_skip_pointers
;
577 std::string m_category
;
578 std::string m_custom_type_name
;
581 OptionGroupOptions m_option_group
;
582 OptionGroupFormat m_format_options
;
583 CommandOptions m_command_options
;
585 Options
*GetOptions() override
{ return &m_option_group
; }
588 CommandObjectTypeFormatAdd(CommandInterpreter
&interpreter
)
589 : CommandObjectParsed(interpreter
, "type format add",
590 "Add a new formatting style for a type.", nullptr),
591 m_format_options(eFormatInvalid
) {
592 AddSimpleArgumentList(eArgTypeName
, eArgRepeatPlus
);
596 The following examples of 'type format add' refer to this code snippet for context:
599 typedef float Afloat;
601 typedef Afloat Bfloat;
609 Adding default formatting:
611 (lldb) type format add -f hex AInt
612 (lldb) frame variable iy
615 " Produces hexadecimal display of iy, because no formatter is available for Bint and \
616 the one for Aint is used instead."
619 To prevent this use the cascade option '-C no' to prevent evaluation of typedef chains:
622 (lldb) type format add -f hex -C no AInt
624 Similar reasoning applies to this:
626 (lldb) type format add -f hex -C no float -p
629 " All float values and float references are now formatted as hexadecimal, but not \
630 pointers to floats. Nor will it change the default display for Afloat and Bfloat objects.");
632 // Add the "--format" to all options groups
633 m_option_group
.Append(&m_format_options
,
634 OptionGroupFormat::OPTION_GROUP_FORMAT
,
636 m_option_group
.Append(&m_command_options
);
637 m_option_group
.Finalize();
640 ~CommandObjectTypeFormatAdd() override
= default;
643 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
644 const size_t argc
= command
.GetArgumentCount();
647 result
.AppendErrorWithFormat("%s takes one or more args.\n",
652 const Format format
= m_format_options
.GetFormat();
653 if (format
== eFormatInvalid
&&
654 m_command_options
.m_custom_type_name
.empty()) {
655 result
.AppendErrorWithFormat("%s needs a valid format.\n",
660 TypeFormatImplSP entry
;
662 if (m_command_options
.m_custom_type_name
.empty())
663 entry
= std::make_shared
<TypeFormatImpl_Format
>(
664 format
, TypeFormatImpl::Flags()
665 .SetCascades(m_command_options
.m_cascade
)
666 .SetSkipPointers(m_command_options
.m_skip_pointers
)
667 .SetSkipReferences(m_command_options
.m_skip_references
));
669 entry
= std::make_shared
<TypeFormatImpl_EnumType
>(
670 ConstString(m_command_options
.m_custom_type_name
.c_str()),
671 TypeFormatImpl::Flags()
672 .SetCascades(m_command_options
.m_cascade
)
673 .SetSkipPointers(m_command_options
.m_skip_pointers
)
674 .SetSkipReferences(m_command_options
.m_skip_references
));
676 // now I have a valid format, let's add it to every type
678 TypeCategoryImplSP category_sp
;
679 DataVisualization::Categories::GetCategory(
680 ConstString(m_command_options
.m_category
), category_sp
);
684 WarnOnPotentialUnquotedUnsignedType(command
, result
);
686 for (auto &arg_entry
: command
.entries()) {
687 if (arg_entry
.ref().empty()) {
688 result
.AppendError("empty typenames not allowed");
692 FormatterMatchType match_type
= eFormatterMatchExact
;
693 if (m_command_options
.m_regex
) {
694 match_type
= eFormatterMatchRegex
;
695 RegularExpression
typeRX(arg_entry
.ref());
696 if (!typeRX
.IsValid()) {
698 "regex format error (maybe this is not really a regex?)");
702 category_sp
->AddTypeFormat(arg_entry
.ref(), match_type
, entry
);
705 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
709 #define LLDB_OPTIONS_type_formatter_delete
710 #include "CommandOptions.inc"
712 class CommandObjectTypeFormatterDelete
: public CommandObjectParsed
{
714 class CommandOptions
: public Options
{
716 CommandOptions() = default;
718 ~CommandOptions() override
= default;
720 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
721 ExecutionContext
*execution_context
) override
{
723 const int short_option
= m_getopt_table
[option_idx
].val
;
725 switch (short_option
) {
730 m_category
= std::string(option_arg
);
733 m_language
= Language::GetLanguageTypeFromString(option_arg
);
736 llvm_unreachable("Unimplemented option");
742 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
743 m_delete_all
= false;
744 m_category
= "default";
745 m_language
= lldb::eLanguageTypeUnknown
;
748 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
749 return llvm::ArrayRef(g_type_formatter_delete_options
);
752 // Instance variables to hold the values for command options.
755 std::string m_category
;
756 lldb::LanguageType m_language
;
759 CommandOptions m_options
;
760 FormatCategoryItem m_formatter_kind
;
762 Options
*GetOptions() override
{ return &m_options
; }
764 static constexpr const char *g_short_help_template
=
765 "Delete an existing %s for a type.";
767 static constexpr const char *g_long_help_template
=
768 "Delete an existing %s for a type. Unless you specify a "
769 "specific category or all categories, only the "
770 "'default' category is searched. The names must be exactly as "
771 "shown in the 'type %s list' output";
774 CommandObjectTypeFormatterDelete(CommandInterpreter
&interpreter
,
775 FormatCategoryItem formatter_kind
)
776 : CommandObjectParsed(interpreter
,
777 FormatCategoryToString(formatter_kind
, false)),
778 m_formatter_kind(formatter_kind
) {
779 AddSimpleArgumentList(eArgTypeName
);
781 const char *kind
= FormatCategoryToString(formatter_kind
, true);
782 const char *short_kind
= FormatCategoryToString(formatter_kind
, false);
785 s
.Printf(g_short_help_template
, kind
);
786 SetHelp(s
.GetData());
788 s
.Printf(g_long_help_template
, kind
, short_kind
);
789 SetHelpLong(s
.GetData());
791 s
.Printf("type %s delete", short_kind
);
792 SetCommandName(s
.GetData());
795 ~CommandObjectTypeFormatterDelete() override
= default;
798 HandleArgumentCompletion(CompletionRequest
&request
,
799 OptionElementVector
&opt_element_vector
) override
{
800 if (request
.GetCursorIndex())
803 DataVisualization::Categories::ForEach(
804 [this, &request
](const lldb::TypeCategoryImplSP
&category_sp
) {
805 category_sp
->AutoComplete(request
, m_formatter_kind
);
811 virtual bool FormatterSpecificDeletion(ConstString typeCS
) { return false; }
813 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
814 const size_t argc
= command
.GetArgumentCount();
817 result
.AppendErrorWithFormat("%s takes 1 arg.\n", m_cmd_name
.c_str());
821 const char *typeA
= command
.GetArgumentAtIndex(0);
822 ConstString
typeCS(typeA
);
825 result
.AppendError("empty typenames not allowed");
829 if (m_options
.m_delete_all
) {
830 DataVisualization::Categories::ForEach(
831 [this, typeCS
](const lldb::TypeCategoryImplSP
&category_sp
) -> bool {
832 category_sp
->Delete(typeCS
, m_formatter_kind
);
835 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
839 bool delete_category
= false;
840 bool extra_deletion
= false;
842 if (m_options
.m_language
!= lldb::eLanguageTypeUnknown
) {
843 lldb::TypeCategoryImplSP category
;
844 DataVisualization::Categories::GetCategory(m_options
.m_language
,
847 delete_category
= category
->Delete(typeCS
, m_formatter_kind
);
848 extra_deletion
= FormatterSpecificDeletion(typeCS
);
850 lldb::TypeCategoryImplSP category
;
851 DataVisualization::Categories::GetCategory(
852 ConstString(m_options
.m_category
.c_str()), category
);
854 delete_category
= category
->Delete(typeCS
, m_formatter_kind
);
855 extra_deletion
= FormatterSpecificDeletion(typeCS
);
858 if (delete_category
|| extra_deletion
) {
859 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
861 result
.AppendErrorWithFormat("no custom formatter for %s.\n", typeA
);
866 #define LLDB_OPTIONS_type_formatter_clear
867 #include "CommandOptions.inc"
869 class CommandObjectTypeFormatterClear
: public CommandObjectParsed
{
871 class CommandOptions
: public Options
{
873 CommandOptions() = default;
875 ~CommandOptions() override
= default;
877 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
878 ExecutionContext
*execution_context
) override
{
880 const int short_option
= m_getopt_table
[option_idx
].val
;
882 switch (short_option
) {
887 llvm_unreachable("Unimplemented option");
893 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
894 m_delete_all
= false;
897 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
898 return llvm::ArrayRef(g_type_formatter_clear_options
);
901 // Instance variables to hold the values for command options.
905 CommandOptions m_options
;
906 FormatCategoryItem m_formatter_kind
;
908 Options
*GetOptions() override
{ return &m_options
; }
911 CommandObjectTypeFormatterClear(CommandInterpreter
&interpreter
,
912 FormatCategoryItem formatter_kind
,
913 const char *name
, const char *help
)
914 : CommandObjectParsed(interpreter
, name
, help
, nullptr),
915 m_formatter_kind(formatter_kind
) {
916 AddSimpleArgumentList(eArgTypeName
, eArgRepeatOptional
);
919 ~CommandObjectTypeFormatterClear() override
= default;
922 virtual void FormatterSpecificDeletion() {}
924 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
925 if (m_options
.m_delete_all
) {
926 DataVisualization::Categories::ForEach(
927 [this](const TypeCategoryImplSP
&category_sp
) -> bool {
928 category_sp
->Clear(m_formatter_kind
);
932 lldb::TypeCategoryImplSP category
;
933 if (command
.GetArgumentCount() > 0) {
934 const char *cat_name
= command
.GetArgumentAtIndex(0);
935 ConstString
cat_nameCS(cat_name
);
936 DataVisualization::Categories::GetCategory(cat_nameCS
, category
);
938 DataVisualization::Categories::GetCategory(ConstString(nullptr),
941 category
->Clear(m_formatter_kind
);
944 FormatterSpecificDeletion();
946 result
.SetStatus(eReturnStatusSuccessFinishResult
);
950 // CommandObjectTypeFormatDelete
952 class CommandObjectTypeFormatDelete
: public CommandObjectTypeFormatterDelete
{
954 CommandObjectTypeFormatDelete(CommandInterpreter
&interpreter
)
955 : CommandObjectTypeFormatterDelete(
956 interpreter
, eFormatCategoryItemFormat
) {}
958 ~CommandObjectTypeFormatDelete() override
= default;
961 // CommandObjectTypeFormatClear
963 class CommandObjectTypeFormatClear
: public CommandObjectTypeFormatterClear
{
965 CommandObjectTypeFormatClear(CommandInterpreter
&interpreter
)
966 : CommandObjectTypeFormatterClear(interpreter
, eFormatCategoryItemFormat
,
968 "Delete all existing format styles.") {}
971 #define LLDB_OPTIONS_type_formatter_list
972 #include "CommandOptions.inc"
974 template <typename FormatterType
>
975 class CommandObjectTypeFormatterList
: public CommandObjectParsed
{
976 typedef typename
FormatterType::SharedPointer FormatterSharedPointer
;
978 class CommandOptions
: public Options
{
981 : Options(), m_category_regex("", ""),
982 m_category_language(lldb::eLanguageTypeUnknown
,
983 lldb::eLanguageTypeUnknown
) {}
985 ~CommandOptions() override
= default;
987 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
988 ExecutionContext
*execution_context
) override
{
990 const int short_option
= m_getopt_table
[option_idx
].val
;
991 switch (short_option
) {
993 m_category_regex
.SetCurrentValue(option_arg
);
994 m_category_regex
.SetOptionWasSet();
997 error
= m_category_language
.SetValueFromString(option_arg
);
999 m_category_language
.SetOptionWasSet();
1002 llvm_unreachable("Unimplemented option");
1008 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
1009 m_category_regex
.Clear();
1010 m_category_language
.Clear();
1013 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
1014 return llvm::ArrayRef(g_type_formatter_list_options
);
1017 // Instance variables to hold the values for command options.
1019 OptionValueString m_category_regex
;
1020 OptionValueLanguage m_category_language
;
1023 CommandOptions m_options
;
1025 Options
*GetOptions() override
{ return &m_options
; }
1028 CommandObjectTypeFormatterList(CommandInterpreter
&interpreter
,
1029 const char *name
, const char *help
)
1030 : CommandObjectParsed(interpreter
, name
, help
, nullptr), m_options() {
1031 AddSimpleArgumentList(eArgTypeName
, eArgRepeatOptional
);
1034 ~CommandObjectTypeFormatterList() override
= default;
1037 virtual bool FormatterSpecificList(CommandReturnObject
&result
) {
1041 static bool ShouldListItem(llvm::StringRef s
, RegularExpression
*regex
) {
1042 // If we have a regex, it can match two kinds of results:
1043 // - An item created with that same regex string (exact string match), so
1044 // the user can list it using the same string it used at creation time.
1045 // - Items that match the regex.
1046 // No regex means list everything.
1047 return regex
== nullptr || s
== regex
->GetText() || regex
->Execute(s
);
1050 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
1051 const size_t argc
= command
.GetArgumentCount();
1053 std::unique_ptr
<RegularExpression
> category_regex
;
1054 std::unique_ptr
<RegularExpression
> formatter_regex
;
1056 if (m_options
.m_category_regex
.OptionWasSet()) {
1057 category_regex
= std::make_unique
<RegularExpression
>(
1058 m_options
.m_category_regex
.GetCurrentValueAsRef());
1059 if (!category_regex
->IsValid()) {
1060 result
.AppendErrorWithFormat(
1061 "syntax error in category regular expression '%s'",
1062 m_options
.m_category_regex
.GetCurrentValueAsRef().str().c_str());
1068 const char *arg
= command
.GetArgumentAtIndex(0);
1069 formatter_regex
= std::make_unique
<RegularExpression
>(arg
);
1070 if (!formatter_regex
->IsValid()) {
1071 result
.AppendErrorWithFormat("syntax error in regular expression '%s'",
1077 bool any_printed
= false;
1079 auto category_closure
=
1080 [&result
, &formatter_regex
,
1081 &any_printed
](const lldb::TypeCategoryImplSP
&category
) -> void {
1082 result
.GetOutputStream().Printf(
1083 "-----------------------\nCategory: %s%s\n-----------------------\n",
1084 category
->GetName(), category
->IsEnabled() ? "" : " (disabled)");
1086 TypeCategoryImpl::ForEachCallback
<FormatterType
> print_formatter
=
1087 [&result
, &formatter_regex
,
1088 &any_printed
](const TypeMatcher
&type_matcher
,
1089 const FormatterSharedPointer
&format_sp
) -> bool {
1090 if (ShouldListItem(type_matcher
.GetMatchString().GetStringRef(),
1091 formatter_regex
.get())) {
1093 result
.GetOutputStream().Printf(
1094 "%s: %s\n", type_matcher
.GetMatchString().GetCString(),
1095 format_sp
->GetDescription().c_str());
1099 category
->ForEach(print_formatter
);
1102 if (m_options
.m_category_language
.OptionWasSet()) {
1103 lldb::TypeCategoryImplSP category_sp
;
1104 DataVisualization::Categories::GetCategory(
1105 m_options
.m_category_language
.GetCurrentValue(), category_sp
);
1107 category_closure(category_sp
);
1109 DataVisualization::Categories::ForEach(
1110 [&category_regex
, &category_closure
](
1111 const lldb::TypeCategoryImplSP
&category
) -> bool {
1112 if (ShouldListItem(category
->GetName(), category_regex
.get())) {
1113 category_closure(category
);
1118 any_printed
= FormatterSpecificList(result
) | any_printed
;
1122 result
.SetStatus(eReturnStatusSuccessFinishResult
);
1124 result
.GetOutputStream().PutCString("no matching results found.\n");
1125 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
1130 // CommandObjectTypeFormatList
1132 class CommandObjectTypeFormatList
1133 : public CommandObjectTypeFormatterList
<TypeFormatImpl
> {
1135 CommandObjectTypeFormatList(CommandInterpreter
&interpreter
)
1136 : CommandObjectTypeFormatterList(interpreter
, "type format list",
1137 "Show a list of current formats.") {}
1140 Status
CommandObjectTypeSummaryAdd::CommandOptions::SetOptionValue(
1141 uint32_t option_idx
, llvm::StringRef option_arg
,
1142 ExecutionContext
*execution_context
) {
1144 const int short_option
= m_getopt_table
[option_idx
].val
;
1147 switch (short_option
) {
1149 m_flags
.SetCascades(OptionArgParser::ToBoolean(option_arg
, true, &success
));
1151 error
= Status::FromErrorStringWithFormat("invalid value for cascade: %s",
1152 option_arg
.str().c_str());
1155 m_flags
.SetDontShowChildren(false);
1158 m_flags
.SetHideEmptyAggregates(true);
1161 m_flags
.SetDontShowValue(true);
1164 m_flags
.SetShowMembersOneLiner(true);
1167 m_format_string
= std::string(option_arg
);
1170 m_flags
.SetSkipPointers(true);
1173 m_flags
.SetSkipReferences(true);
1176 if (m_match_type
== eFormatterMatchCallback
)
1177 error
= Status::FromErrorString(
1178 "can't use --regex and --recognizer-function at the same time");
1180 m_match_type
= eFormatterMatchRegex
;
1183 if (m_match_type
== eFormatterMatchRegex
)
1184 error
= Status::FromErrorString(
1185 "can't use --regex and --recognizer-function at the same time");
1187 m_match_type
= eFormatterMatchCallback
;
1190 m_name
.SetString(option_arg
);
1193 m_python_script
= std::string(option_arg
);
1194 m_is_add_script
= true;
1197 m_python_function
= std::string(option_arg
);
1198 m_is_add_script
= true;
1201 m_is_add_script
= true;
1204 m_category
= std::string(option_arg
);
1207 m_flags
.SetHideItemNames(true);
1210 llvm_unreachable("Unimplemented option");
1216 void CommandObjectTypeSummaryAdd::CommandOptions::OptionParsingStarting(
1217 ExecutionContext
*execution_context
) {
1218 m_flags
.Clear().SetCascades().SetDontShowChildren().SetDontShowValue(false);
1219 m_flags
.SetShowMembersOneLiner(false)
1220 .SetSkipPointers(false)
1221 .SetSkipReferences(false)
1222 .SetHideItemNames(false);
1224 m_match_type
= eFormatterMatchExact
;
1226 m_python_script
= "";
1227 m_python_function
= "";
1228 m_format_string
= "";
1229 m_is_add_script
= false;
1230 m_category
= "default";
1233 #if LLDB_ENABLE_PYTHON
1235 bool CommandObjectTypeSummaryAdd::Execute_ScriptSummary(
1236 Args
&command
, CommandReturnObject
&result
) {
1237 const size_t argc
= command
.GetArgumentCount();
1239 if (argc
< 1 && !m_options
.m_name
) {
1240 result
.AppendErrorWithFormat("%s takes one or more args.\n",
1241 m_cmd_name
.c_str());
1245 TypeSummaryImplSP script_format
;
1247 if (!m_options
.m_python_function
1248 .empty()) // we have a Python function ready to use
1250 const char *funct_name
= m_options
.m_python_function
.c_str();
1251 if (!funct_name
|| !funct_name
[0]) {
1252 result
.AppendError("function name empty.\n");
1257 (" " + m_options
.m_python_function
+ "(valobj,internal_dict)");
1259 script_format
= std::make_shared
<ScriptSummaryFormat
>(
1260 m_options
.m_flags
, funct_name
, code
.c_str());
1262 ScriptInterpreter
*interpreter
= GetDebugger().GetScriptInterpreter();
1264 if (interpreter
&& !interpreter
->CheckObjectExists(funct_name
))
1265 result
.AppendWarningWithFormat(
1266 "The provided function \"%s\" does not exist - "
1267 "please define it before attempting to use this summary.\n",
1269 } else if (!m_options
.m_python_script
1270 .empty()) // we have a quick 1-line script, just use it
1272 ScriptInterpreter
*interpreter
= GetDebugger().GetScriptInterpreter();
1274 result
.AppendError("script interpreter missing - unable to generate "
1275 "function wrapper.\n");
1278 StringList funct_sl
;
1279 funct_sl
<< m_options
.m_python_script
.c_str();
1280 std::string funct_name_str
;
1281 if (!interpreter
->GenerateTypeScriptFunction(funct_sl
, funct_name_str
)) {
1282 result
.AppendError("unable to generate function wrapper.\n");
1285 if (funct_name_str
.empty()) {
1287 "script interpreter failed to generate a valid function name.\n");
1291 std::string code
= " " + m_options
.m_python_script
;
1293 script_format
= std::make_shared
<ScriptSummaryFormat
>(
1294 m_options
.m_flags
, funct_name_str
.c_str(), code
.c_str());
1296 // Use an IOHandler to grab Python code from the user
1297 auto options
= std::make_unique
<ScriptAddOptions
>(
1298 m_options
.m_flags
, m_options
.m_match_type
, m_options
.m_name
,
1299 m_options
.m_category
);
1301 for (auto &entry
: command
.entries()) {
1302 if (entry
.ref().empty()) {
1303 result
.AppendError("empty typenames not allowed");
1307 options
->m_target_types
<< std::string(entry
.ref());
1310 m_interpreter
.GetPythonCommandsFromIOHandler(
1312 *this, // IOHandlerDelegate
1313 options
.release()); // Baton for the "io_handler" that will be passed
1314 // back into our IOHandlerDelegate functions
1315 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
1317 return result
.Succeeded();
1320 // if I am here, script_format must point to something good, so I can add
1321 // that as a script summary to all interested parties
1325 for (auto &entry
: command
.entries()) {
1326 AddSummary(ConstString(entry
.ref()), script_format
, m_options
.m_match_type
,
1327 m_options
.m_category
, &error
);
1329 result
.AppendError(error
.AsCString());
1334 if (m_options
.m_name
) {
1335 AddNamedSummary(m_options
.m_name
, script_format
, &error
);
1337 result
.AppendError(error
.AsCString());
1338 result
.AppendError("added to types, but not given a name");
1343 return result
.Succeeded();
1348 bool CommandObjectTypeSummaryAdd::Execute_StringSummary(
1349 Args
&command
, CommandReturnObject
&result
) {
1350 const size_t argc
= command
.GetArgumentCount();
1352 if (argc
< 1 && !m_options
.m_name
) {
1353 result
.AppendErrorWithFormat("%s takes one or more args.\n",
1354 m_cmd_name
.c_str());
1358 if (!m_options
.m_flags
.GetShowMembersOneLiner() &&
1359 m_options
.m_format_string
.empty()) {
1360 result
.AppendError("empty summary strings not allowed");
1364 const char *format_cstr
= (m_options
.m_flags
.GetShowMembersOneLiner()
1366 : m_options
.m_format_string
.c_str());
1368 // ${var%S} is an endless recursion, prevent it
1369 if (strcmp(format_cstr
, "${var%S}") == 0) {
1370 result
.AppendError("recursive summary not allowed");
1374 std::unique_ptr
<StringSummaryFormat
> string_format(
1375 new StringSummaryFormat(m_options
.m_flags
, format_cstr
));
1376 if (!string_format
) {
1377 result
.AppendError("summary creation failed");
1380 if (string_format
->m_error
.Fail()) {
1381 result
.AppendErrorWithFormat("syntax error: %s",
1382 string_format
->m_error
.AsCString("<unknown>"));
1385 lldb::TypeSummaryImplSP
entry(string_format
.release());
1387 // now I have a valid format, let's add it to every type
1389 for (auto &arg_entry
: command
.entries()) {
1390 if (arg_entry
.ref().empty()) {
1391 result
.AppendError("empty typenames not allowed");
1394 ConstString
typeCS(arg_entry
.ref());
1396 AddSummary(typeCS
, entry
, m_options
.m_match_type
, m_options
.m_category
,
1400 result
.AppendError(error
.AsCString());
1405 if (m_options
.m_name
) {
1406 AddNamedSummary(m_options
.m_name
, entry
, &error
);
1408 result
.AppendError(error
.AsCString());
1409 result
.AppendError("added to types, but not given a name");
1414 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
1415 return result
.Succeeded();
1418 CommandObjectTypeSummaryAdd::CommandObjectTypeSummaryAdd(
1419 CommandInterpreter
&interpreter
)
1420 : CommandObjectParsed(interpreter
, "type summary add",
1421 "Add a new summary style for a type.", nullptr),
1422 IOHandlerDelegateMultiline("DONE"), m_options(interpreter
) {
1423 AddSimpleArgumentList(eArgTypeName
, eArgRepeatPlus
);
1427 The following examples of 'type summary add' refer to this code snippet for context:
1433 JustADemo(int p = 1, float v = 0.1) : ptr(new int(p)), value(v) {}
1435 JustADemo demo_instance(42, 3.14);
1437 typedef JustADemo NewDemo;
1438 NewDemo new_demo_instance(42, 3.14);
1440 (lldb) type summary add --summary-string "the answer is $
{*var
.ptr
}" JustADemo
1442 Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is
42"
1444 (lldb) type summary add --summary-string "the answer is $
{*var
.ptr
}, and the question is $
{var
.value
}" JustADemo
1446 Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is
42 and the question is
3.14"
1449 "Alternatively, you could define formatting for all pointers to integers and \
1450 rely on that when formatting JustADemo to obtain the same result:"
1453 (lldb) type summary add --summary-string "$
{var
%V
} -> $
{*var
}" "int *"
1454 (lldb) type summary add --summary-string "the answer is $
{var
.ptr
}, and the question is $
{var
.value
}" JustADemo
1457 "Type summaries are automatically applied to derived typedefs, so the examples \
1458 above apply to both JustADemo and NewDemo. The cascade option can be used to \
1459 suppress this behavior:"
1462 (lldb) type summary add --summary-string "$
{var
.ptr
}, $
{var
.value
},{$
{var
.byte
}}" JustADemo -C no
1464 The summary will now be used for values of JustADemo but not NewDemo.
1467 "By default summaries are shown for pointers and references to values of the \
1468 specified type. To suppress formatting for pointers use the -p option, or apply \
1469 the corresponding -r option to suppress formatting for references:"
1472 (lldb) type summary add -p -r --summary-string "$
{var
.ptr
}, $
{var
.value
},{$
{var
.byte
}}" JustADemo
1475 "One-line summaries including all fields in a type can be inferred without supplying an \
1476 explicit summary string by passing the -c option:"
1479 (lldb) type summary add -c JustADemo
1480 (lldb) frame variable demo_instance
1481 (ptr=<address>, value=3.14)
1484 "Type summaries normally suppress the nested display of individual fields. To \
1485 supply a summary to supplement the default structure add the -e option:"
1488 (lldb) type summary add -e --summary-string "*ptr
= $
{*var
.ptr
}" JustADemo
1491 "Now when displaying JustADemo values the int* is displayed, followed by the \
1492 standard LLDB sequence of children, one per line:"
1501 "You can also add summaries written in Python. These scripts use lldb public API to \
1502 gather information from your variables and produce a meaningful summary. To start a \
1503 multi-line script use the -P option. The function declaration will be displayed along with \
1504 a comment describing the two arguments. End your script with the word 'DONE' on a line by \
1508 (lldb) type summary add JustADemo -P
1509 def function (valobj,internal_dict):
1510 """valobj
: an SBValue which you want to provide a summary
for
1511 internal_dict
: an LLDB support object
not to be used
"""
1512 value = valobj.GetChildMemberWithName('value');
1513 return 'My value is ' + value.GetValue();
1516 Alternatively, the -o option can be used when providing a simple one-line Python script:
1518 (lldb) type summary add JustADemo -o "value
= valobj
.GetChildMemberWithName('value'); return 'My value is ' + value
.GetValue();")");
1521 void CommandObjectTypeSummaryAdd::DoExecute(Args
&command
,
1522 CommandReturnObject
&result
) {
1523 WarnOnPotentialUnquotedUnsignedType(command
, result
);
1525 if (m_options
.m_is_add_script
) {
1526 #if LLDB_ENABLE_PYTHON
1527 Execute_ScriptSummary(command
, result
);
1529 result
.AppendError("python is disabled");
1534 Execute_StringSummary(command
, result
);
1537 static bool FixArrayTypeNameWithRegex(ConstString
&type_name
) {
1538 llvm::StringRef
type_name_ref(type_name
.GetStringRef());
1540 if (type_name_ref
.ends_with("[]")) {
1541 std::string
type_name_str(type_name
.GetCString());
1542 type_name_str
.resize(type_name_str
.length() - 2);
1543 if (type_name_str
.back() != ' ')
1544 type_name_str
.append(" ?\\[[0-9]+\\]");
1546 type_name_str
.append("\\[[0-9]+\\]");
1547 type_name
.SetCString(type_name_str
.c_str());
1553 bool CommandObjectTypeSummaryAdd::AddNamedSummary(ConstString summary_name
,
1554 TypeSummaryImplSP entry
,
1556 // system named summaries do not exist (yet?)
1557 DataVisualization::NamedSummaryFormats::Add(summary_name
, entry
);
1561 bool CommandObjectTypeSummaryAdd::AddSummary(ConstString type_name
,
1562 TypeSummaryImplSP entry
,
1563 FormatterMatchType match_type
,
1564 std::string category_name
,
1566 lldb::TypeCategoryImplSP category
;
1567 DataVisualization::Categories::GetCategory(ConstString(category_name
.c_str()),
1570 if (match_type
== eFormatterMatchExact
) {
1571 if (FixArrayTypeNameWithRegex(type_name
))
1572 match_type
= eFormatterMatchRegex
;
1575 if (match_type
== eFormatterMatchRegex
) {
1576 match_type
= eFormatterMatchRegex
;
1577 RegularExpression
typeRX(type_name
.GetStringRef());
1578 if (!typeRX
.IsValid()) {
1580 *error
= Status::FromErrorString(
1581 "regex format error (maybe this is not really a regex?)");
1586 if (match_type
== eFormatterMatchCallback
) {
1587 const char *function_name
= type_name
.AsCString();
1588 ScriptInterpreter
*interpreter
= GetDebugger().GetScriptInterpreter();
1589 if (interpreter
&& !interpreter
->CheckObjectExists(function_name
)) {
1590 *error
= Status::FromErrorStringWithFormat(
1591 "The provided recognizer function \"%s\" does not exist - "
1592 "please define it before attempting to use this summary.\n",
1597 category
->AddTypeSummary(type_name
.GetStringRef(), match_type
, entry
);
1601 // CommandObjectTypeSummaryDelete
1603 class CommandObjectTypeSummaryDelete
: public CommandObjectTypeFormatterDelete
{
1605 CommandObjectTypeSummaryDelete(CommandInterpreter
&interpreter
)
1606 : CommandObjectTypeFormatterDelete(
1607 interpreter
, eFormatCategoryItemSummary
) {}
1609 ~CommandObjectTypeSummaryDelete() override
= default;
1612 bool FormatterSpecificDeletion(ConstString typeCS
) override
{
1613 if (m_options
.m_language
!= lldb::eLanguageTypeUnknown
)
1615 return DataVisualization::NamedSummaryFormats::Delete(typeCS
);
1619 class CommandObjectTypeSummaryClear
: public CommandObjectTypeFormatterClear
{
1621 CommandObjectTypeSummaryClear(CommandInterpreter
&interpreter
)
1622 : CommandObjectTypeFormatterClear(interpreter
, eFormatCategoryItemSummary
,
1623 "type summary clear",
1624 "Delete all existing summaries.") {}
1627 void FormatterSpecificDeletion() override
{
1628 DataVisualization::NamedSummaryFormats::Clear();
1632 // CommandObjectTypeSummaryList
1634 class CommandObjectTypeSummaryList
1635 : public CommandObjectTypeFormatterList
<TypeSummaryImpl
> {
1637 CommandObjectTypeSummaryList(CommandInterpreter
&interpreter
)
1638 : CommandObjectTypeFormatterList(interpreter
, "type summary list",
1639 "Show a list of current summaries.") {}
1642 bool FormatterSpecificList(CommandReturnObject
&result
) override
{
1643 if (DataVisualization::NamedSummaryFormats::GetCount() > 0) {
1644 result
.GetOutputStream().Printf("Named summaries:\n");
1645 DataVisualization::NamedSummaryFormats::ForEach(
1646 [&result
](const TypeMatcher
&type_matcher
,
1647 const TypeSummaryImplSP
&summary_sp
) -> bool {
1648 result
.GetOutputStream().Printf(
1649 "%s: %s\n", type_matcher
.GetMatchString().GetCString(),
1650 summary_sp
->GetDescription().c_str());
1659 // CommandObjectTypeCategoryDefine
1660 #define LLDB_OPTIONS_type_category_define
1661 #include "CommandOptions.inc"
1663 class CommandObjectTypeCategoryDefine
: public CommandObjectParsed
{
1664 class CommandOptions
: public Options
{
1667 : m_define_enabled(false, false),
1668 m_cate_language(eLanguageTypeUnknown
, eLanguageTypeUnknown
) {}
1670 ~CommandOptions() override
= default;
1672 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
1673 ExecutionContext
*execution_context
) override
{
1675 const int short_option
= m_getopt_table
[option_idx
].val
;
1677 switch (short_option
) {
1679 m_define_enabled
.SetValueFromString(llvm::StringRef("true"));
1682 error
= m_cate_language
.SetValueFromString(option_arg
);
1685 llvm_unreachable("Unimplemented option");
1691 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
1692 m_define_enabled
.Clear();
1693 m_cate_language
.Clear();
1696 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
1697 return llvm::ArrayRef(g_type_category_define_options
);
1700 // Instance variables to hold the values for command options.
1702 OptionValueBoolean m_define_enabled
;
1703 OptionValueLanguage m_cate_language
;
1706 CommandOptions m_options
;
1708 Options
*GetOptions() override
{ return &m_options
; }
1711 CommandObjectTypeCategoryDefine(CommandInterpreter
&interpreter
)
1712 : CommandObjectParsed(interpreter
, "type category define",
1713 "Define a new category as a source of formatters.",
1715 AddSimpleArgumentList(eArgTypeName
, eArgRepeatPlus
);
1718 ~CommandObjectTypeCategoryDefine() override
= default;
1721 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
1722 const size_t argc
= command
.GetArgumentCount();
1725 result
.AppendErrorWithFormat("%s takes 1 or more args.\n",
1726 m_cmd_name
.c_str());
1730 for (auto &entry
: command
.entries()) {
1731 TypeCategoryImplSP category_sp
;
1732 if (DataVisualization::Categories::GetCategory(ConstString(entry
.ref()),
1735 category_sp
->AddLanguage(m_options
.m_cate_language
.GetCurrentValue());
1736 if (m_options
.m_define_enabled
.GetCurrentValue())
1737 DataVisualization::Categories::Enable(category_sp
,
1738 TypeCategoryMap::Default
);
1742 result
.SetStatus(eReturnStatusSuccessFinishResult
);
1746 // CommandObjectTypeCategoryEnable
1747 #define LLDB_OPTIONS_type_category_enable
1748 #include "CommandOptions.inc"
1750 class CommandObjectTypeCategoryEnable
: public CommandObjectParsed
{
1751 class CommandOptions
: public Options
{
1753 CommandOptions() = default;
1755 ~CommandOptions() override
= default;
1757 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
1758 ExecutionContext
*execution_context
) override
{
1760 const int short_option
= m_getopt_table
[option_idx
].val
;
1762 switch (short_option
) {
1764 if (!option_arg
.empty()) {
1765 m_language
= Language::GetLanguageTypeFromString(option_arg
);
1766 if (m_language
== lldb::eLanguageTypeUnknown
)
1767 error
= Status::FromErrorStringWithFormat(
1768 "unrecognized language '%s'", option_arg
.str().c_str());
1772 llvm_unreachable("Unimplemented option");
1778 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
1779 m_language
= lldb::eLanguageTypeUnknown
;
1782 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
1783 return llvm::ArrayRef(g_type_category_enable_options
);
1786 // Instance variables to hold the values for command options.
1788 lldb::LanguageType m_language
;
1791 CommandOptions m_options
;
1793 Options
*GetOptions() override
{ return &m_options
; }
1796 CommandObjectTypeCategoryEnable(CommandInterpreter
&interpreter
)
1797 : CommandObjectParsed(interpreter
, "type category enable",
1798 "Enable a category as a source of formatters.",
1800 AddSimpleArgumentList(eArgTypeName
, eArgRepeatPlus
);
1803 ~CommandObjectTypeCategoryEnable() override
= default;
1806 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
1807 const size_t argc
= command
.GetArgumentCount();
1809 if (argc
< 1 && m_options
.m_language
== lldb::eLanguageTypeUnknown
) {
1810 result
.AppendErrorWithFormat("%s takes arguments and/or a language",
1811 m_cmd_name
.c_str());
1815 if (argc
== 1 && strcmp(command
.GetArgumentAtIndex(0), "*") == 0) {
1816 DataVisualization::Categories::EnableStar();
1817 } else if (argc
> 0) {
1818 for (int i
= argc
- 1; i
>= 0; i
--) {
1819 const char *typeA
= command
.GetArgumentAtIndex(i
);
1820 ConstString
typeCS(typeA
);
1823 result
.AppendError("empty category name not allowed");
1826 DataVisualization::Categories::Enable(typeCS
);
1827 lldb::TypeCategoryImplSP cate
;
1828 if (DataVisualization::Categories::GetCategory(typeCS
, cate
) && cate
) {
1829 if (cate
->GetCount() == 0) {
1830 result
.AppendWarning("empty category enabled (typo?)");
1836 if (m_options
.m_language
!= lldb::eLanguageTypeUnknown
)
1837 DataVisualization::Categories::Enable(m_options
.m_language
);
1839 result
.SetStatus(eReturnStatusSuccessFinishResult
);
1843 // CommandObjectTypeCategoryDelete
1845 class CommandObjectTypeCategoryDelete
: public CommandObjectParsed
{
1847 CommandObjectTypeCategoryDelete(CommandInterpreter
&interpreter
)
1848 : CommandObjectParsed(interpreter
, "type category delete",
1849 "Delete a category and all associated formatters.",
1851 AddSimpleArgumentList(eArgTypeName
, eArgRepeatPlus
);
1854 ~CommandObjectTypeCategoryDelete() override
= default;
1857 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
1858 const size_t argc
= command
.GetArgumentCount();
1861 result
.AppendErrorWithFormat("%s takes 1 or more arg.\n",
1862 m_cmd_name
.c_str());
1866 bool success
= true;
1868 // the order is not relevant here
1869 for (int i
= argc
- 1; i
>= 0; i
--) {
1870 const char *typeA
= command
.GetArgumentAtIndex(i
);
1871 ConstString
typeCS(typeA
);
1874 result
.AppendError("empty category name not allowed");
1877 if (!DataVisualization::Categories::Delete(typeCS
))
1878 success
= false; // keep deleting even if we hit an error
1881 result
.SetStatus(eReturnStatusSuccessFinishResult
);
1883 result
.AppendError("cannot delete one or more categories\n");
1888 // CommandObjectTypeCategoryDisable
1889 #define LLDB_OPTIONS_type_category_disable
1890 #include "CommandOptions.inc"
1892 class CommandObjectTypeCategoryDisable
: public CommandObjectParsed
{
1893 class CommandOptions
: public Options
{
1895 CommandOptions() = default;
1897 ~CommandOptions() override
= default;
1899 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
1900 ExecutionContext
*execution_context
) override
{
1902 const int short_option
= m_getopt_table
[option_idx
].val
;
1904 switch (short_option
) {
1906 if (!option_arg
.empty()) {
1907 m_language
= Language::GetLanguageTypeFromString(option_arg
);
1908 if (m_language
== lldb::eLanguageTypeUnknown
)
1909 error
= Status::FromErrorStringWithFormat(
1910 "unrecognized language '%s'", option_arg
.str().c_str());
1914 llvm_unreachable("Unimplemented option");
1920 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
1921 m_language
= lldb::eLanguageTypeUnknown
;
1924 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
1925 return llvm::ArrayRef(g_type_category_disable_options
);
1928 // Instance variables to hold the values for command options.
1930 lldb::LanguageType m_language
;
1933 CommandOptions m_options
;
1935 Options
*GetOptions() override
{ return &m_options
; }
1938 CommandObjectTypeCategoryDisable(CommandInterpreter
&interpreter
)
1939 : CommandObjectParsed(interpreter
, "type category disable",
1940 "Disable a category as a source of formatters.",
1942 AddSimpleArgumentList(eArgTypeName
, eArgRepeatPlus
);
1945 ~CommandObjectTypeCategoryDisable() override
= default;
1948 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
1949 const size_t argc
= command
.GetArgumentCount();
1951 if (argc
< 1 && m_options
.m_language
== lldb::eLanguageTypeUnknown
) {
1952 result
.AppendErrorWithFormat("%s takes arguments and/or a language",
1953 m_cmd_name
.c_str());
1957 if (argc
== 1 && strcmp(command
.GetArgumentAtIndex(0), "*") == 0) {
1958 DataVisualization::Categories::DisableStar();
1959 } else if (argc
> 0) {
1960 // the order is not relevant here
1961 for (int i
= argc
- 1; i
>= 0; i
--) {
1962 const char *typeA
= command
.GetArgumentAtIndex(i
);
1963 ConstString
typeCS(typeA
);
1966 result
.AppendError("empty category name not allowed");
1969 DataVisualization::Categories::Disable(typeCS
);
1973 if (m_options
.m_language
!= lldb::eLanguageTypeUnknown
)
1974 DataVisualization::Categories::Disable(m_options
.m_language
);
1976 result
.SetStatus(eReturnStatusSuccessFinishResult
);
1980 // CommandObjectTypeCategoryList
1982 class CommandObjectTypeCategoryList
: public CommandObjectParsed
{
1984 CommandObjectTypeCategoryList(CommandInterpreter
&interpreter
)
1985 : CommandObjectParsed(interpreter
, "type category list",
1986 "Provide a list of all existing categories.",
1988 AddSimpleArgumentList(eArgTypeName
, eArgRepeatOptional
);
1991 ~CommandObjectTypeCategoryList() override
= default;
1994 HandleArgumentCompletion(CompletionRequest
&request
,
1995 OptionElementVector
&opt_element_vector
) override
{
1996 if (request
.GetCursorIndex())
1998 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1999 GetCommandInterpreter(), lldb::eTypeCategoryNameCompletion
, request
,
2004 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
2005 const size_t argc
= command
.GetArgumentCount();
2007 std::unique_ptr
<RegularExpression
> regex
;
2010 const char *arg
= command
.GetArgumentAtIndex(0);
2011 regex
= std::make_unique
<RegularExpression
>(arg
);
2012 if (!regex
->IsValid()) {
2013 result
.AppendErrorWithFormat(
2014 "syntax error in category regular expression '%s'", arg
);
2017 } else if (argc
!= 0) {
2018 result
.AppendErrorWithFormat("%s takes 0 or one arg.\n",
2019 m_cmd_name
.c_str());
2023 DataVisualization::Categories::ForEach(
2024 [®ex
, &result
](const lldb::TypeCategoryImplSP
&category_sp
) -> bool {
2027 if (regex
->GetText() == category_sp
->GetName()) {
2029 } else if (regex
->Execute(category_sp
->GetName())) {
2037 result
.GetOutputStream().Printf(
2038 "Category: %s\n", category_sp
->GetDescription().c_str());
2043 result
.SetStatus(eReturnStatusSuccessFinishResult
);
2047 // CommandObjectTypeFilterList
2049 class CommandObjectTypeFilterList
2050 : public CommandObjectTypeFormatterList
<TypeFilterImpl
> {
2052 CommandObjectTypeFilterList(CommandInterpreter
&interpreter
)
2053 : CommandObjectTypeFormatterList(interpreter
, "type filter list",
2054 "Show a list of current filters.") {}
2057 // CommandObjectTypeSynthList
2059 class CommandObjectTypeSynthList
2060 : public CommandObjectTypeFormatterList
<SyntheticChildren
> {
2062 CommandObjectTypeSynthList(CommandInterpreter
&interpreter
)
2063 : CommandObjectTypeFormatterList(
2064 interpreter
, "type synthetic list",
2065 "Show a list of current synthetic providers.") {}
2068 // CommandObjectTypeFilterDelete
2070 class CommandObjectTypeFilterDelete
: public CommandObjectTypeFormatterDelete
{
2072 CommandObjectTypeFilterDelete(CommandInterpreter
&interpreter
)
2073 : CommandObjectTypeFormatterDelete(
2074 interpreter
, eFormatCategoryItemFilter
) {}
2076 ~CommandObjectTypeFilterDelete() override
= default;
2079 // CommandObjectTypeSynthDelete
2081 class CommandObjectTypeSynthDelete
: public CommandObjectTypeFormatterDelete
{
2083 CommandObjectTypeSynthDelete(CommandInterpreter
&interpreter
)
2084 : CommandObjectTypeFormatterDelete(
2085 interpreter
, eFormatCategoryItemSynth
) {}
2087 ~CommandObjectTypeSynthDelete() override
= default;
2091 // CommandObjectTypeFilterClear
2093 class CommandObjectTypeFilterClear
: public CommandObjectTypeFormatterClear
{
2095 CommandObjectTypeFilterClear(CommandInterpreter
&interpreter
)
2096 : CommandObjectTypeFormatterClear(interpreter
, eFormatCategoryItemFilter
,
2097 "type filter clear",
2098 "Delete all existing filter.") {}
2101 // CommandObjectTypeSynthClear
2103 class CommandObjectTypeSynthClear
: public CommandObjectTypeFormatterClear
{
2105 CommandObjectTypeSynthClear(CommandInterpreter
&interpreter
)
2106 : CommandObjectTypeFormatterClear(
2107 interpreter
, eFormatCategoryItemSynth
, "type synthetic clear",
2108 "Delete all existing synthetic providers.") {}
2111 bool CommandObjectTypeSynthAdd::Execute_HandwritePython(
2112 Args
&command
, CommandReturnObject
&result
) {
2113 auto options
= std::make_unique
<SynthAddOptions
>(
2114 m_options
.m_skip_pointers
, m_options
.m_skip_references
,
2115 m_options
.m_cascade
, m_options
.m_match_type
, m_options
.m_category
);
2117 for (auto &entry
: command
.entries()) {
2118 if (entry
.ref().empty()) {
2119 result
.AppendError("empty typenames not allowed");
2123 options
->m_target_types
<< std::string(entry
.ref());
2126 m_interpreter
.GetPythonCommandsFromIOHandler(
2128 *this, // IOHandlerDelegate
2129 options
.release()); // Baton for the "io_handler" that will be passed back
2130 // into our IOHandlerDelegate functions
2131 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
2132 return result
.Succeeded();
2135 bool CommandObjectTypeSynthAdd::Execute_PythonClass(
2136 Args
&command
, CommandReturnObject
&result
) {
2137 const size_t argc
= command
.GetArgumentCount();
2140 result
.AppendErrorWithFormat("%s takes one or more args.\n",
2141 m_cmd_name
.c_str());
2145 if (m_options
.m_class_name
.empty() && !m_options
.m_input_python
) {
2146 result
.AppendErrorWithFormat("%s needs either a Python class name or -P to "
2147 "directly input Python code.\n",
2148 m_cmd_name
.c_str());
2152 SyntheticChildrenSP entry
;
2154 ScriptedSyntheticChildren
*impl
= new ScriptedSyntheticChildren(
2155 SyntheticChildren::Flags()
2156 .SetCascades(m_options
.m_cascade
)
2157 .SetSkipPointers(m_options
.m_skip_pointers
)
2158 .SetSkipReferences(m_options
.m_skip_references
),
2159 m_options
.m_class_name
.c_str());
2163 ScriptInterpreter
*interpreter
= GetDebugger().GetScriptInterpreter();
2166 !interpreter
->CheckObjectExists(impl
->GetPythonClassName()))
2167 result
.AppendWarning("The provided class does not exist - please define it "
2168 "before attempting to use this synthetic provider");
2170 // now I have a valid provider, let's add it to every type
2172 lldb::TypeCategoryImplSP category
;
2173 DataVisualization::Categories::GetCategory(
2174 ConstString(m_options
.m_category
.c_str()), category
);
2178 for (auto &arg_entry
: command
.entries()) {
2179 if (arg_entry
.ref().empty()) {
2180 result
.AppendError("empty typenames not allowed");
2184 ConstString
typeCS(arg_entry
.ref());
2185 if (!AddSynth(typeCS
, entry
, m_options
.m_match_type
, m_options
.m_category
,
2187 result
.AppendError(error
.AsCString());
2192 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
2193 return result
.Succeeded();
2196 CommandObjectTypeSynthAdd::CommandObjectTypeSynthAdd(
2197 CommandInterpreter
&interpreter
)
2198 : CommandObjectParsed(interpreter
, "type synthetic add",
2199 "Add a new synthetic provider for a type.", nullptr),
2200 IOHandlerDelegateMultiline("DONE"), m_options() {
2201 AddSimpleArgumentList(eArgTypeName
, eArgRepeatPlus
);
2204 bool CommandObjectTypeSynthAdd::AddSynth(ConstString type_name
,
2205 SyntheticChildrenSP entry
,
2206 FormatterMatchType match_type
,
2207 std::string category_name
,
2209 lldb::TypeCategoryImplSP category
;
2210 DataVisualization::Categories::GetCategory(ConstString(category_name
.c_str()),
2213 if (match_type
== eFormatterMatchExact
) {
2214 if (FixArrayTypeNameWithRegex(type_name
))
2215 match_type
= eFormatterMatchRegex
;
2218 // Only check for conflicting filters in the same category if `type_name` is
2219 // an actual type name. Matching a regex string against registered regexes
2221 if (match_type
== eFormatterMatchExact
) {
2222 // It's not generally possible to get a type object here. For example, this
2223 // command can be run before loading any binaries. Do just a best-effort
2224 // name-based lookup here to try to prevent conflicts.
2225 FormattersMatchCandidate
candidate_type(type_name
, nullptr, TypeImpl(),
2226 FormattersMatchCandidate::Flags());
2227 if (category
->AnyMatches(candidate_type
, eFormatCategoryItemFilter
,
2230 *error
= Status::FromErrorStringWithFormat(
2231 "cannot add synthetic for type %s when "
2232 "filter is defined in same category!",
2233 type_name
.AsCString());
2238 if (match_type
== eFormatterMatchRegex
) {
2239 RegularExpression
typeRX(type_name
.GetStringRef());
2240 if (!typeRX
.IsValid()) {
2242 *error
= Status::FromErrorString(
2243 "regex format error (maybe this is not really a regex?)");
2248 if (match_type
== eFormatterMatchCallback
) {
2249 const char *function_name
= type_name
.AsCString();
2250 ScriptInterpreter
*interpreter
= GetDebugger().GetScriptInterpreter();
2251 if (interpreter
&& !interpreter
->CheckObjectExists(function_name
)) {
2252 *error
= Status::FromErrorStringWithFormat(
2253 "The provided recognizer function \"%s\" does not exist - "
2254 "please define it before attempting to use this summary.\n",
2260 category
->AddTypeSynthetic(type_name
.GetStringRef(), match_type
, entry
);
2264 #define LLDB_OPTIONS_type_filter_add
2265 #include "CommandOptions.inc"
2267 class CommandObjectTypeFilterAdd
: public CommandObjectParsed
{
2269 class CommandOptions
: public Options
{
2270 typedef std::vector
<std::string
> option_vector
;
2273 CommandOptions() = default;
2275 ~CommandOptions() override
= default;
2277 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
2278 ExecutionContext
*execution_context
) override
{
2280 const int short_option
= m_getopt_table
[option_idx
].val
;
2283 switch (short_option
) {
2285 m_cascade
= OptionArgParser::ToBoolean(option_arg
, true, &success
);
2287 error
= Status::FromErrorStringWithFormat(
2288 "invalid value for cascade: %s", option_arg
.str().c_str());
2291 m_expr_paths
.push_back(std::string(option_arg
));
2292 has_child_list
= true;
2295 m_skip_pointers
= true;
2298 m_skip_references
= true;
2301 m_category
= std::string(option_arg
);
2307 llvm_unreachable("Unimplemented option");
2313 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
2315 m_skip_pointers
= false;
2316 m_skip_references
= false;
2317 m_category
= "default";
2318 m_expr_paths
.clear();
2319 has_child_list
= false;
2323 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
2324 return llvm::ArrayRef(g_type_filter_add_options
);
2327 // Instance variables to hold the values for command options.
2330 bool m_skip_references
;
2331 bool m_skip_pointers
;
2332 bool m_input_python
;
2333 option_vector m_expr_paths
;
2334 std::string m_category
;
2335 bool has_child_list
;
2338 typedef option_vector::iterator ExpressionPathsIterator
;
2341 CommandOptions m_options
;
2343 Options
*GetOptions() override
{ return &m_options
; }
2345 enum FilterFormatType
{ eRegularFilter
, eRegexFilter
};
2347 bool AddFilter(ConstString type_name
, TypeFilterImplSP entry
,
2348 FilterFormatType type
, std::string category_name
,
2350 lldb::TypeCategoryImplSP category
;
2351 DataVisualization::Categories::GetCategory(
2352 ConstString(category_name
.c_str()), category
);
2354 if (type
== eRegularFilter
) {
2355 if (FixArrayTypeNameWithRegex(type_name
))
2356 type
= eRegexFilter
;
2359 // Only check for conflicting synthetic child providers in the same category
2360 // if `type_name` is an actual type name. Matching a regex string against
2361 // registered regexes doesn't work.
2362 if (type
== eRegularFilter
) {
2363 // It's not generally possible to get a type object here. For example,
2364 // this command can be run before loading any binaries. Do just a
2365 // best-effort name-based lookup here to try to prevent conflicts.
2366 FormattersMatchCandidate
candidate_type(
2367 type_name
, nullptr, TypeImpl(), FormattersMatchCandidate::Flags());
2368 lldb::SyntheticChildrenSP entry
;
2369 if (category
->AnyMatches(candidate_type
, eFormatCategoryItemSynth
,
2372 *error
= Status::FromErrorStringWithFormat(
2373 "cannot add filter for type %s when "
2374 "synthetic is defined in same "
2376 type_name
.AsCString());
2381 FormatterMatchType match_type
= eFormatterMatchExact
;
2382 if (type
== eRegexFilter
) {
2383 match_type
= eFormatterMatchRegex
;
2384 RegularExpression
typeRX(type_name
.GetStringRef());
2385 if (!typeRX
.IsValid()) {
2387 *error
= Status::FromErrorString(
2388 "regex format error (maybe this is not really a regex?)");
2392 category
->AddTypeFilter(type_name
.GetStringRef(), match_type
, entry
);
2397 CommandObjectTypeFilterAdd(CommandInterpreter
&interpreter
)
2398 : CommandObjectParsed(interpreter
, "type filter add",
2399 "Add a new filter for a type.", nullptr) {
2400 AddSimpleArgumentList(eArgTypeName
, eArgRepeatPlus
);
2404 The following examples of 'type filter add' refer to this code snippet for context:
2419 Adding a simple filter:
2421 (lldb) type filter add --child a --child g Foo
2422 (lldb) frame variable my_foo
2425 "Produces output where only a and g are displayed. Other children of my_foo \
2426 (b, c, d, e, f, h and i) are available by asking for them explicitly:"
2429 (lldb) frame variable my_foo.b my_foo.c my_foo.i
2432 "The formatting option --raw on frame variable bypasses the filter, showing \
2433 all children of my_foo as if no filter was defined:"
2436 (lldb) frame variable my_foo --raw)");
2439 ~CommandObjectTypeFilterAdd() override
= default;
2442 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
2443 const size_t argc
= command
.GetArgumentCount();
2446 result
.AppendErrorWithFormat("%s takes one or more args.\n",
2447 m_cmd_name
.c_str());
2451 if (m_options
.m_expr_paths
.empty()) {
2452 result
.AppendErrorWithFormat("%s needs one or more children.\n",
2453 m_cmd_name
.c_str());
2457 TypeFilterImplSP
entry(new TypeFilterImpl(
2458 SyntheticChildren::Flags()
2459 .SetCascades(m_options
.m_cascade
)
2460 .SetSkipPointers(m_options
.m_skip_pointers
)
2461 .SetSkipReferences(m_options
.m_skip_references
)));
2463 // go through the expression paths
2464 CommandOptions::ExpressionPathsIterator begin
,
2465 end
= m_options
.m_expr_paths
.end();
2467 for (begin
= m_options
.m_expr_paths
.begin(); begin
!= end
; begin
++)
2468 entry
->AddExpressionPath(*begin
);
2470 // now I have a valid provider, let's add it to every type
2472 lldb::TypeCategoryImplSP category
;
2473 DataVisualization::Categories::GetCategory(
2474 ConstString(m_options
.m_category
.c_str()), category
);
2478 WarnOnPotentialUnquotedUnsignedType(command
, result
);
2480 for (auto &arg_entry
: command
.entries()) {
2481 if (arg_entry
.ref().empty()) {
2482 result
.AppendError("empty typenames not allowed");
2486 ConstString
typeCS(arg_entry
.ref());
2487 if (!AddFilter(typeCS
, entry
,
2488 m_options
.m_regex
? eRegexFilter
: eRegularFilter
,
2489 m_options
.m_category
, &error
)) {
2490 result
.AppendError(error
.AsCString());
2495 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
2500 #define LLDB_OPTIONS_type_lookup
2501 #include "CommandOptions.inc"
2503 class CommandObjectTypeLookup
: public CommandObjectRaw
{
2505 // this function is allowed to do a more aggressive job at guessing languages
2506 // than the expression parser is comfortable with - so leave the original
2507 // call alone and add one that is specific to type lookup
2508 lldb::LanguageType
GuessLanguage(StackFrame
*frame
) {
2509 lldb::LanguageType lang_type
= lldb::eLanguageTypeUnknown
;
2514 lang_type
= frame
->GuessLanguage().AsLanguageType();
2515 if (lang_type
!= lldb::eLanguageTypeUnknown
)
2518 Symbol
*s
= frame
->GetSymbolContext(eSymbolContextSymbol
).symbol
;
2520 lang_type
= s
->GetMangled().GuessLanguage();
2525 class CommandOptions
: public OptionGroup
{
2527 CommandOptions() = default;
2529 ~CommandOptions() override
= default;
2531 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
2532 return llvm::ArrayRef(g_type_lookup_options
);
2535 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_value
,
2536 ExecutionContext
*execution_context
) override
{
2539 const int short_option
= g_type_lookup_options
[option_idx
].short_option
;
2541 switch (short_option
) {
2547 m_language
= Language::GetLanguageTypeFromString(option_value
);
2551 llvm_unreachable("Unimplemented option");
2557 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
2558 m_show_help
= false;
2559 m_language
= eLanguageTypeUnknown
;
2562 // Options table: Required for subclasses of Options.
2564 bool m_show_help
= false;
2565 lldb::LanguageType m_language
= eLanguageTypeUnknown
;
2568 OptionGroupOptions m_option_group
;
2569 CommandOptions m_command_options
;
2572 CommandObjectTypeLookup(CommandInterpreter
&interpreter
)
2573 : CommandObjectRaw(interpreter
, "type lookup",
2574 "Lookup types and declarations in the current target, "
2575 "following language-specific naming conventions.",
2576 "type lookup <type-specifier>",
2577 eCommandRequiresTarget
) {
2578 m_option_group
.Append(&m_command_options
);
2579 m_option_group
.Finalize();
2582 ~CommandObjectTypeLookup() override
= default;
2584 Options
*GetOptions() override
{ return &m_option_group
; }
2586 llvm::StringRef
GetHelpLong() override
{
2587 if (!m_cmd_help_long
.empty())
2588 return m_cmd_help_long
;
2590 StreamString stream
;
2591 Language::ForEach([&](Language
*lang
) {
2592 if (const char *help
= lang
->GetLanguageSpecificTypeLookupHelp())
2593 stream
.Printf("%s\n", help
);
2597 m_cmd_help_long
= std::string(stream
.GetString());
2598 return m_cmd_help_long
;
2601 void DoExecute(llvm::StringRef raw_command_line
,
2602 CommandReturnObject
&result
) override
{
2603 if (raw_command_line
.empty()) {
2605 "type lookup cannot be invoked without a type name as argument");
2609 auto exe_ctx
= GetCommandInterpreter().GetExecutionContext();
2610 m_option_group
.NotifyOptionParsingStarting(&exe_ctx
);
2612 OptionsWithRaw
args(raw_command_line
);
2613 const char *name_of_type
= args
.GetRawPart().c_str();
2616 if (!ParseOptionsAndNotify(args
.GetArgs(), result
, m_option_group
,
2620 ExecutionContextScope
*best_scope
= exe_ctx
.GetBestExecutionContextScope();
2622 bool any_found
= false;
2624 std::vector
<Language
*> languages
;
2626 bool is_global_search
= false;
2627 LanguageType guessed_language
= lldb::eLanguageTypeUnknown
;
2629 if ((is_global_search
=
2630 (m_command_options
.m_language
== eLanguageTypeUnknown
))) {
2631 Language::ForEach([&](Language
*lang
) {
2632 languages
.push_back(lang
);
2636 languages
.push_back(Language::FindPlugin(m_command_options
.m_language
));
2639 // This is not the most efficient way to do this, but we support very few
2640 // languages so the cost of the sort is going to be dwarfed by the actual
2642 if (StackFrame
*frame
= m_exe_ctx
.GetFramePtr()) {
2643 guessed_language
= GuessLanguage(frame
);
2644 if (guessed_language
!= eLanguageTypeUnknown
) {
2646 languages
.begin(), languages
.end(),
2647 [guessed_language
](Language
*lang1
, Language
*lang2
) -> bool {
2648 if (!lang1
|| !lang2
)
2650 LanguageType lt1
= lang1
->GetLanguageType();
2651 LanguageType lt2
= lang2
->GetLanguageType();
2654 if (lt1
== guessed_language
)
2655 return true; // make the selected frame's language come first
2656 if (lt2
== guessed_language
)
2657 return false; // make the selected frame's language come first
2658 return (lt1
< lt2
); // normal comparison otherwise
2663 bool is_first_language
= true;
2665 for (Language
*language
: languages
) {
2669 if (auto scavenger
= language
->GetTypeScavenger()) {
2670 Language::TypeScavenger::ResultSet search_results
;
2671 if (scavenger
->Find(best_scope
, name_of_type
, search_results
) > 0) {
2672 for (const auto &search_result
: search_results
) {
2673 if (search_result
&& search_result
->IsValid()) {
2675 search_result
->DumpToStream(result
.GetOutputStream(),
2676 this->m_command_options
.m_show_help
);
2681 // this is "type lookup SomeName" and we did find a match, so get out
2682 if (any_found
&& is_global_search
)
2684 else if (is_first_language
&& is_global_search
&&
2685 guessed_language
!= lldb::eLanguageTypeUnknown
) {
2686 is_first_language
= false;
2687 result
.GetOutputStream().Printf(
2688 "no type was found in the current language %s matching '%s'; "
2689 "performing a global search across all languages\n",
2690 Language::GetNameForLanguageType(guessed_language
), name_of_type
);
2695 result
.AppendMessageWithFormat("no type was found matching '%s'\n",
2698 result
.SetStatus(any_found
? lldb::eReturnStatusSuccessFinishResult
2699 : lldb::eReturnStatusSuccessFinishNoResult
);
2703 template <typename FormatterType
>
2704 class CommandObjectFormatterInfo
: public CommandObjectRaw
{
2706 typedef std::function
<typename
FormatterType::SharedPointer(ValueObject
&)>
2708 CommandObjectFormatterInfo(CommandInterpreter
&interpreter
,
2709 const char *formatter_name
,
2710 DiscoveryFunction discovery_func
)
2711 : CommandObjectRaw(interpreter
, "", "", "", eCommandRequiresFrame
),
2712 m_formatter_name(formatter_name
? formatter_name
: ""),
2713 m_discovery_function(discovery_func
) {
2715 name
.Printf("type %s info", formatter_name
);
2716 SetCommandName(name
.GetString());
2718 help
.Printf("This command evaluates the provided expression and shows "
2719 "which %s is applied to the resulting value (if any).",
2721 SetHelp(help
.GetString());
2722 StreamString syntax
;
2723 syntax
.Printf("type %s info <expr>", formatter_name
);
2724 SetSyntax(syntax
.GetString());
2727 ~CommandObjectFormatterInfo() override
= default;
2730 void DoExecute(llvm::StringRef command
,
2731 CommandReturnObject
&result
) override
{
2732 TargetSP target_sp
= GetDebugger().GetSelectedTarget();
2733 Thread
*thread
= GetDefaultThread();
2735 result
.AppendError("no default thread");
2739 StackFrameSP frame_sp
=
2740 thread
->GetSelectedFrame(DoNoSelectMostRelevantFrame
);
2741 ValueObjectSP result_valobj_sp
;
2742 EvaluateExpressionOptions options
;
2743 lldb::ExpressionResults expr_result
= target_sp
->EvaluateExpression(
2744 command
, frame_sp
.get(), result_valobj_sp
, options
);
2745 if (expr_result
== eExpressionCompleted
&& result_valobj_sp
) {
2747 result_valobj_sp
->GetQualifiedRepresentationIfAvailable(
2748 target_sp
->GetPreferDynamicValue(),
2749 target_sp
->GetEnableSyntheticValue());
2750 typename
FormatterType::SharedPointer formatter_sp
=
2751 m_discovery_function(*result_valobj_sp
);
2753 std::string
description(formatter_sp
->GetDescription());
2754 result
.GetOutputStream()
2755 << m_formatter_name
<< " applied to ("
2756 << result_valobj_sp
->GetDisplayTypeName().AsCString("<unknown>")
2757 << ") " << command
<< " is: " << description
<< "\n";
2758 result
.SetStatus(lldb::eReturnStatusSuccessFinishResult
);
2760 result
.GetOutputStream()
2761 << "no " << m_formatter_name
<< " applies to ("
2762 << result_valobj_sp
->GetDisplayTypeName().AsCString("<unknown>")
2763 << ") " << command
<< "\n";
2764 result
.SetStatus(lldb::eReturnStatusSuccessFinishNoResult
);
2767 result
.AppendError("failed to evaluate expression");
2772 std::string m_formatter_name
;
2773 DiscoveryFunction m_discovery_function
;
2776 class CommandObjectTypeFormat
: public CommandObjectMultiword
{
2778 CommandObjectTypeFormat(CommandInterpreter
&interpreter
)
2779 : CommandObjectMultiword(
2780 interpreter
, "type format",
2781 "Commands for customizing value display formats.",
2782 "type format [<sub-command-options>] ") {
2784 "add", CommandObjectSP(new CommandObjectTypeFormatAdd(interpreter
)));
2785 LoadSubCommand("clear", CommandObjectSP(
2786 new CommandObjectTypeFormatClear(interpreter
)));
2787 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFormatDelete(
2790 "list", CommandObjectSP(new CommandObjectTypeFormatList(interpreter
)));
2792 "info", CommandObjectSP(new CommandObjectFormatterInfo
<TypeFormatImpl
>(
2793 interpreter
, "format",
2794 [](ValueObject
&valobj
) -> TypeFormatImpl::SharedPointer
{
2795 return valobj
.GetValueFormat();
2799 ~CommandObjectTypeFormat() override
= default;
2802 class CommandObjectTypeSynth
: public CommandObjectMultiword
{
2804 CommandObjectTypeSynth(CommandInterpreter
&interpreter
)
2805 : CommandObjectMultiword(
2806 interpreter
, "type synthetic",
2807 "Commands for operating on synthetic type representations.",
2808 "type synthetic [<sub-command-options>] ") {
2809 LoadSubCommand("add",
2810 CommandObjectSP(new CommandObjectTypeSynthAdd(interpreter
)));
2812 "clear", CommandObjectSP(new CommandObjectTypeSynthClear(interpreter
)));
2813 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSynthDelete(
2816 "list", CommandObjectSP(new CommandObjectTypeSynthList(interpreter
)));
2819 CommandObjectSP(new CommandObjectFormatterInfo
<SyntheticChildren
>(
2820 interpreter
, "synthetic",
2821 [](ValueObject
&valobj
) -> SyntheticChildren::SharedPointer
{
2822 return valobj
.GetSyntheticChildren();
2826 ~CommandObjectTypeSynth() override
= default;
2829 class CommandObjectTypeFilter
: public CommandObjectMultiword
{
2831 CommandObjectTypeFilter(CommandInterpreter
&interpreter
)
2832 : CommandObjectMultiword(interpreter
, "type filter",
2833 "Commands for operating on type filters.",
2834 "type filter [<sub-command-options>] ") {
2836 "add", CommandObjectSP(new CommandObjectTypeFilterAdd(interpreter
)));
2837 LoadSubCommand("clear", CommandObjectSP(
2838 new CommandObjectTypeFilterClear(interpreter
)));
2839 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFilterDelete(
2842 "list", CommandObjectSP(new CommandObjectTypeFilterList(interpreter
)));
2845 ~CommandObjectTypeFilter() override
= default;
2848 class CommandObjectTypeCategory
: public CommandObjectMultiword
{
2850 CommandObjectTypeCategory(CommandInterpreter
&interpreter
)
2851 : CommandObjectMultiword(interpreter
, "type category",
2852 "Commands for operating on type categories.",
2853 "type category [<sub-command-options>] ") {
2856 CommandObjectSP(new CommandObjectTypeCategoryDefine(interpreter
)));
2859 CommandObjectSP(new CommandObjectTypeCategoryEnable(interpreter
)));
2862 CommandObjectSP(new CommandObjectTypeCategoryDisable(interpreter
)));
2865 CommandObjectSP(new CommandObjectTypeCategoryDelete(interpreter
)));
2866 LoadSubCommand("list", CommandObjectSP(
2867 new CommandObjectTypeCategoryList(interpreter
)));
2870 ~CommandObjectTypeCategory() override
= default;
2873 class CommandObjectTypeSummary
: public CommandObjectMultiword
{
2875 CommandObjectTypeSummary(CommandInterpreter
&interpreter
)
2876 : CommandObjectMultiword(
2877 interpreter
, "type summary",
2878 "Commands for editing variable summary display options.",
2879 "type summary [<sub-command-options>] ") {
2881 "add", CommandObjectSP(new CommandObjectTypeSummaryAdd(interpreter
)));
2882 LoadSubCommand("clear", CommandObjectSP(new CommandObjectTypeSummaryClear(
2884 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSummaryDelete(
2887 "list", CommandObjectSP(new CommandObjectTypeSummaryList(interpreter
)));
2889 "info", CommandObjectSP(new CommandObjectFormatterInfo
<TypeSummaryImpl
>(
2890 interpreter
, "summary",
2891 [](ValueObject
&valobj
) -> TypeSummaryImpl::SharedPointer
{
2892 return valobj
.GetSummaryFormat();
2896 ~CommandObjectTypeSummary() override
= default;
2899 // CommandObjectType
2901 CommandObjectType::CommandObjectType(CommandInterpreter
&interpreter
)
2902 : CommandObjectMultiword(interpreter
, "type",
2903 "Commands for operating on the type system.",
2904 "type [<sub-command-options>]") {
2905 LoadSubCommand("category",
2906 CommandObjectSP(new CommandObjectTypeCategory(interpreter
)));
2907 LoadSubCommand("filter",
2908 CommandObjectSP(new CommandObjectTypeFilter(interpreter
)));
2909 LoadSubCommand("format",
2910 CommandObjectSP(new CommandObjectTypeFormat(interpreter
)));
2911 LoadSubCommand("summary",
2912 CommandObjectSP(new CommandObjectTypeSummary(interpreter
)));
2913 LoadSubCommand("synthetic",
2914 CommandObjectSP(new CommandObjectTypeSynth(interpreter
)));
2915 LoadSubCommand("lookup",
2916 CommandObjectSP(new CommandObjectTypeLookup(interpreter
)));
2919 CommandObjectType::~CommandObjectType() = default;