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
.SetErrorStringWithFormat("invalid value for cascade: %s",
316 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
.SetErrorString(
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
.SetErrorString(
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
.SetErrorStringWithFormat("invalid value for cascade: %s",
547 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 CommandArgumentEntry type_arg
;
593 CommandArgumentData type_style_arg
;
595 type_style_arg
.arg_type
= eArgTypeName
;
596 type_style_arg
.arg_repetition
= eArgRepeatPlus
;
598 type_arg
.push_back(type_style_arg
);
600 m_arguments
.push_back(type_arg
);
604 The following examples of 'type format add' refer to this code snippet for context:
607 typedef float Afloat;
609 typedef Afloat Bfloat;
617 Adding default formatting:
619 (lldb) type format add -f hex AInt
620 (lldb) frame variable iy
623 " Produces hexadecimal display of iy, because no formatter is available for Bint and \
624 the one for Aint is used instead."
627 To prevent this use the cascade option '-C no' to prevent evaluation of typedef chains:
630 (lldb) type format add -f hex -C no AInt
632 Similar reasoning applies to this:
634 (lldb) type format add -f hex -C no float -p
637 " All float values and float references are now formatted as hexadecimal, but not \
638 pointers to floats. Nor will it change the default display for Afloat and Bfloat objects.");
640 // Add the "--format" to all options groups
641 m_option_group
.Append(&m_format_options
,
642 OptionGroupFormat::OPTION_GROUP_FORMAT
,
644 m_option_group
.Append(&m_command_options
);
645 m_option_group
.Finalize();
648 ~CommandObjectTypeFormatAdd() override
= default;
651 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
652 const size_t argc
= command
.GetArgumentCount();
655 result
.AppendErrorWithFormat("%s takes one or more args.\n",
660 const Format format
= m_format_options
.GetFormat();
661 if (format
== eFormatInvalid
&&
662 m_command_options
.m_custom_type_name
.empty()) {
663 result
.AppendErrorWithFormat("%s needs a valid format.\n",
668 TypeFormatImplSP entry
;
670 if (m_command_options
.m_custom_type_name
.empty())
671 entry
= std::make_shared
<TypeFormatImpl_Format
>(
672 format
, TypeFormatImpl::Flags()
673 .SetCascades(m_command_options
.m_cascade
)
674 .SetSkipPointers(m_command_options
.m_skip_pointers
)
675 .SetSkipReferences(m_command_options
.m_skip_references
));
677 entry
= std::make_shared
<TypeFormatImpl_EnumType
>(
678 ConstString(m_command_options
.m_custom_type_name
.c_str()),
679 TypeFormatImpl::Flags()
680 .SetCascades(m_command_options
.m_cascade
)
681 .SetSkipPointers(m_command_options
.m_skip_pointers
)
682 .SetSkipReferences(m_command_options
.m_skip_references
));
684 // now I have a valid format, let's add it to every type
686 TypeCategoryImplSP category_sp
;
687 DataVisualization::Categories::GetCategory(
688 ConstString(m_command_options
.m_category
), category_sp
);
692 WarnOnPotentialUnquotedUnsignedType(command
, result
);
694 for (auto &arg_entry
: command
.entries()) {
695 if (arg_entry
.ref().empty()) {
696 result
.AppendError("empty typenames not allowed");
700 FormatterMatchType match_type
= eFormatterMatchExact
;
701 if (m_command_options
.m_regex
) {
702 match_type
= eFormatterMatchRegex
;
703 RegularExpression
typeRX(arg_entry
.ref());
704 if (!typeRX
.IsValid()) {
706 "regex format error (maybe this is not really a regex?)");
710 category_sp
->AddTypeFormat(arg_entry
.ref(), match_type
, entry
);
713 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
717 #define LLDB_OPTIONS_type_formatter_delete
718 #include "CommandOptions.inc"
720 class CommandObjectTypeFormatterDelete
: public CommandObjectParsed
{
722 class CommandOptions
: public Options
{
724 CommandOptions() = default;
726 ~CommandOptions() override
= default;
728 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
729 ExecutionContext
*execution_context
) override
{
731 const int short_option
= m_getopt_table
[option_idx
].val
;
733 switch (short_option
) {
738 m_category
= std::string(option_arg
);
741 m_language
= Language::GetLanguageTypeFromString(option_arg
);
744 llvm_unreachable("Unimplemented option");
750 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
751 m_delete_all
= false;
752 m_category
= "default";
753 m_language
= lldb::eLanguageTypeUnknown
;
756 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
757 return llvm::ArrayRef(g_type_formatter_delete_options
);
760 // Instance variables to hold the values for command options.
763 std::string m_category
;
764 lldb::LanguageType m_language
;
767 CommandOptions m_options
;
768 FormatCategoryItem m_formatter_kind
;
770 Options
*GetOptions() override
{ return &m_options
; }
772 static constexpr const char *g_short_help_template
=
773 "Delete an existing %s for a type.";
775 static constexpr const char *g_long_help_template
=
776 "Delete an existing %s for a type. Unless you specify a "
777 "specific category or all categories, only the "
778 "'default' category is searched. The names must be exactly as "
779 "shown in the 'type %s list' output";
782 CommandObjectTypeFormatterDelete(CommandInterpreter
&interpreter
,
783 FormatCategoryItem formatter_kind
)
784 : CommandObjectParsed(interpreter
,
785 FormatCategoryToString(formatter_kind
, false)),
786 m_formatter_kind(formatter_kind
) {
787 CommandArgumentEntry type_arg
;
788 CommandArgumentData type_style_arg
;
790 type_style_arg
.arg_type
= eArgTypeName
;
791 type_style_arg
.arg_repetition
= eArgRepeatPlain
;
793 type_arg
.push_back(type_style_arg
);
795 m_arguments
.push_back(type_arg
);
797 const char *kind
= FormatCategoryToString(formatter_kind
, true);
798 const char *short_kind
= FormatCategoryToString(formatter_kind
, false);
801 s
.Printf(g_short_help_template
, kind
);
802 SetHelp(s
.GetData());
804 s
.Printf(g_long_help_template
, kind
, short_kind
);
805 SetHelpLong(s
.GetData());
807 s
.Printf("type %s delete", short_kind
);
808 SetCommandName(s
.GetData());
811 ~CommandObjectTypeFormatterDelete() override
= default;
814 HandleArgumentCompletion(CompletionRequest
&request
,
815 OptionElementVector
&opt_element_vector
) override
{
816 if (request
.GetCursorIndex())
819 DataVisualization::Categories::ForEach(
820 [this, &request
](const lldb::TypeCategoryImplSP
&category_sp
) {
821 category_sp
->AutoComplete(request
, m_formatter_kind
);
827 virtual bool FormatterSpecificDeletion(ConstString typeCS
) { return false; }
829 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
830 const size_t argc
= command
.GetArgumentCount();
833 result
.AppendErrorWithFormat("%s takes 1 arg.\n", m_cmd_name
.c_str());
837 const char *typeA
= command
.GetArgumentAtIndex(0);
838 ConstString
typeCS(typeA
);
841 result
.AppendError("empty typenames not allowed");
845 if (m_options
.m_delete_all
) {
846 DataVisualization::Categories::ForEach(
847 [this, typeCS
](const lldb::TypeCategoryImplSP
&category_sp
) -> bool {
848 category_sp
->Delete(typeCS
, m_formatter_kind
);
851 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
855 bool delete_category
= false;
856 bool extra_deletion
= false;
858 if (m_options
.m_language
!= lldb::eLanguageTypeUnknown
) {
859 lldb::TypeCategoryImplSP category
;
860 DataVisualization::Categories::GetCategory(m_options
.m_language
,
863 delete_category
= category
->Delete(typeCS
, m_formatter_kind
);
864 extra_deletion
= FormatterSpecificDeletion(typeCS
);
866 lldb::TypeCategoryImplSP category
;
867 DataVisualization::Categories::GetCategory(
868 ConstString(m_options
.m_category
.c_str()), category
);
870 delete_category
= category
->Delete(typeCS
, m_formatter_kind
);
871 extra_deletion
= FormatterSpecificDeletion(typeCS
);
874 if (delete_category
|| extra_deletion
) {
875 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
877 result
.AppendErrorWithFormat("no custom formatter for %s.\n", typeA
);
882 #define LLDB_OPTIONS_type_formatter_clear
883 #include "CommandOptions.inc"
885 class CommandObjectTypeFormatterClear
: public CommandObjectParsed
{
887 class CommandOptions
: public Options
{
889 CommandOptions() = default;
891 ~CommandOptions() override
= default;
893 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
894 ExecutionContext
*execution_context
) override
{
896 const int short_option
= m_getopt_table
[option_idx
].val
;
898 switch (short_option
) {
903 llvm_unreachable("Unimplemented option");
909 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
910 m_delete_all
= false;
913 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
914 return llvm::ArrayRef(g_type_formatter_clear_options
);
917 // Instance variables to hold the values for command options.
921 CommandOptions m_options
;
922 FormatCategoryItem m_formatter_kind
;
924 Options
*GetOptions() override
{ return &m_options
; }
927 CommandObjectTypeFormatterClear(CommandInterpreter
&interpreter
,
928 FormatCategoryItem formatter_kind
,
929 const char *name
, const char *help
)
930 : CommandObjectParsed(interpreter
, name
, help
, nullptr),
931 m_formatter_kind(formatter_kind
) {
932 CommandArgumentData category_arg
{eArgTypeName
, eArgRepeatOptional
};
933 m_arguments
.push_back({category_arg
});
936 ~CommandObjectTypeFormatterClear() override
= default;
939 virtual void FormatterSpecificDeletion() {}
941 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
942 if (m_options
.m_delete_all
) {
943 DataVisualization::Categories::ForEach(
944 [this](const TypeCategoryImplSP
&category_sp
) -> bool {
945 category_sp
->Clear(m_formatter_kind
);
949 lldb::TypeCategoryImplSP category
;
950 if (command
.GetArgumentCount() > 0) {
951 const char *cat_name
= command
.GetArgumentAtIndex(0);
952 ConstString
cat_nameCS(cat_name
);
953 DataVisualization::Categories::GetCategory(cat_nameCS
, category
);
955 DataVisualization::Categories::GetCategory(ConstString(nullptr),
958 category
->Clear(m_formatter_kind
);
961 FormatterSpecificDeletion();
963 result
.SetStatus(eReturnStatusSuccessFinishResult
);
967 // CommandObjectTypeFormatDelete
969 class CommandObjectTypeFormatDelete
: public CommandObjectTypeFormatterDelete
{
971 CommandObjectTypeFormatDelete(CommandInterpreter
&interpreter
)
972 : CommandObjectTypeFormatterDelete(
973 interpreter
, eFormatCategoryItemFormat
) {}
975 ~CommandObjectTypeFormatDelete() override
= default;
978 // CommandObjectTypeFormatClear
980 class CommandObjectTypeFormatClear
: public CommandObjectTypeFormatterClear
{
982 CommandObjectTypeFormatClear(CommandInterpreter
&interpreter
)
983 : CommandObjectTypeFormatterClear(interpreter
, eFormatCategoryItemFormat
,
985 "Delete all existing format styles.") {}
988 #define LLDB_OPTIONS_type_formatter_list
989 #include "CommandOptions.inc"
991 template <typename FormatterType
>
992 class CommandObjectTypeFormatterList
: public CommandObjectParsed
{
993 typedef typename
FormatterType::SharedPointer FormatterSharedPointer
;
995 class CommandOptions
: public Options
{
998 : Options(), m_category_regex("", ""),
999 m_category_language(lldb::eLanguageTypeUnknown
,
1000 lldb::eLanguageTypeUnknown
) {}
1002 ~CommandOptions() override
= default;
1004 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
1005 ExecutionContext
*execution_context
) override
{
1007 const int short_option
= m_getopt_table
[option_idx
].val
;
1008 switch (short_option
) {
1010 m_category_regex
.SetCurrentValue(option_arg
);
1011 m_category_regex
.SetOptionWasSet();
1014 error
= m_category_language
.SetValueFromString(option_arg
);
1015 if (error
.Success())
1016 m_category_language
.SetOptionWasSet();
1019 llvm_unreachable("Unimplemented option");
1025 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
1026 m_category_regex
.Clear();
1027 m_category_language
.Clear();
1030 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
1031 return llvm::ArrayRef(g_type_formatter_list_options
);
1034 // Instance variables to hold the values for command options.
1036 OptionValueString m_category_regex
;
1037 OptionValueLanguage m_category_language
;
1040 CommandOptions m_options
;
1042 Options
*GetOptions() override
{ return &m_options
; }
1045 CommandObjectTypeFormatterList(CommandInterpreter
&interpreter
,
1046 const char *name
, const char *help
)
1047 : CommandObjectParsed(interpreter
, name
, help
, nullptr), m_options() {
1048 CommandArgumentEntry type_arg
;
1049 CommandArgumentData type_style_arg
;
1051 type_style_arg
.arg_type
= eArgTypeName
;
1052 type_style_arg
.arg_repetition
= eArgRepeatOptional
;
1054 type_arg
.push_back(type_style_arg
);
1056 m_arguments
.push_back(type_arg
);
1059 ~CommandObjectTypeFormatterList() override
= default;
1062 virtual bool FormatterSpecificList(CommandReturnObject
&result
) {
1066 static bool ShouldListItem(llvm::StringRef s
, RegularExpression
*regex
) {
1067 // If we have a regex, it can match two kinds of results:
1068 // - An item created with that same regex string (exact string match), so
1069 // the user can list it using the same string it used at creation time.
1070 // - Items that match the regex.
1071 // No regex means list everything.
1072 return regex
== nullptr || s
== regex
->GetText() || regex
->Execute(s
);
1075 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
1076 const size_t argc
= command
.GetArgumentCount();
1078 std::unique_ptr
<RegularExpression
> category_regex
;
1079 std::unique_ptr
<RegularExpression
> formatter_regex
;
1081 if (m_options
.m_category_regex
.OptionWasSet()) {
1082 category_regex
= std::make_unique
<RegularExpression
>(
1083 m_options
.m_category_regex
.GetCurrentValueAsRef());
1084 if (!category_regex
->IsValid()) {
1085 result
.AppendErrorWithFormat(
1086 "syntax error in category regular expression '%s'",
1087 m_options
.m_category_regex
.GetCurrentValueAsRef().str().c_str());
1093 const char *arg
= command
.GetArgumentAtIndex(0);
1094 formatter_regex
= std::make_unique
<RegularExpression
>(arg
);
1095 if (!formatter_regex
->IsValid()) {
1096 result
.AppendErrorWithFormat("syntax error in regular expression '%s'",
1102 bool any_printed
= false;
1104 auto category_closure
=
1105 [&result
, &formatter_regex
,
1106 &any_printed
](const lldb::TypeCategoryImplSP
&category
) -> void {
1107 result
.GetOutputStream().Printf(
1108 "-----------------------\nCategory: %s%s\n-----------------------\n",
1109 category
->GetName(), category
->IsEnabled() ? "" : " (disabled)");
1111 TypeCategoryImpl::ForEachCallback
<FormatterType
> print_formatter
=
1112 [&result
, &formatter_regex
,
1113 &any_printed
](const TypeMatcher
&type_matcher
,
1114 const FormatterSharedPointer
&format_sp
) -> bool {
1115 if (ShouldListItem(type_matcher
.GetMatchString().GetStringRef(),
1116 formatter_regex
.get())) {
1118 result
.GetOutputStream().Printf(
1119 "%s: %s\n", type_matcher
.GetMatchString().GetCString(),
1120 format_sp
->GetDescription().c_str());
1124 category
->ForEach(print_formatter
);
1127 if (m_options
.m_category_language
.OptionWasSet()) {
1128 lldb::TypeCategoryImplSP category_sp
;
1129 DataVisualization::Categories::GetCategory(
1130 m_options
.m_category_language
.GetCurrentValue(), category_sp
);
1132 category_closure(category_sp
);
1134 DataVisualization::Categories::ForEach(
1135 [&category_regex
, &category_closure
](
1136 const lldb::TypeCategoryImplSP
&category
) -> bool {
1137 if (ShouldListItem(category
->GetName(), category_regex
.get())) {
1138 category_closure(category
);
1143 any_printed
= FormatterSpecificList(result
) | any_printed
;
1147 result
.SetStatus(eReturnStatusSuccessFinishResult
);
1149 result
.GetOutputStream().PutCString("no matching results found.\n");
1150 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
1155 // CommandObjectTypeFormatList
1157 class CommandObjectTypeFormatList
1158 : public CommandObjectTypeFormatterList
<TypeFormatImpl
> {
1160 CommandObjectTypeFormatList(CommandInterpreter
&interpreter
)
1161 : CommandObjectTypeFormatterList(interpreter
, "type format list",
1162 "Show a list of current formats.") {}
1165 Status
CommandObjectTypeSummaryAdd::CommandOptions::SetOptionValue(
1166 uint32_t option_idx
, llvm::StringRef option_arg
,
1167 ExecutionContext
*execution_context
) {
1169 const int short_option
= m_getopt_table
[option_idx
].val
;
1172 switch (short_option
) {
1174 m_flags
.SetCascades(OptionArgParser::ToBoolean(option_arg
, true, &success
));
1176 error
.SetErrorStringWithFormat("invalid value for cascade: %s",
1177 option_arg
.str().c_str());
1180 m_flags
.SetDontShowChildren(false);
1183 m_flags
.SetHideEmptyAggregates(true);
1186 m_flags
.SetDontShowValue(true);
1189 m_flags
.SetShowMembersOneLiner(true);
1192 m_format_string
= std::string(option_arg
);
1195 m_flags
.SetSkipPointers(true);
1198 m_flags
.SetSkipReferences(true);
1201 if (m_match_type
== eFormatterMatchCallback
)
1202 error
.SetErrorString(
1203 "can't use --regex and --recognizer-function at the same time");
1205 m_match_type
= eFormatterMatchRegex
;
1208 if (m_match_type
== eFormatterMatchRegex
)
1209 error
.SetErrorString(
1210 "can't use --regex and --recognizer-function at the same time");
1212 m_match_type
= eFormatterMatchCallback
;
1215 m_name
.SetString(option_arg
);
1218 m_python_script
= std::string(option_arg
);
1219 m_is_add_script
= true;
1222 m_python_function
= std::string(option_arg
);
1223 m_is_add_script
= true;
1226 m_is_add_script
= true;
1229 m_category
= std::string(option_arg
);
1232 m_flags
.SetHideItemNames(true);
1235 llvm_unreachable("Unimplemented option");
1241 void CommandObjectTypeSummaryAdd::CommandOptions::OptionParsingStarting(
1242 ExecutionContext
*execution_context
) {
1243 m_flags
.Clear().SetCascades().SetDontShowChildren().SetDontShowValue(false);
1244 m_flags
.SetShowMembersOneLiner(false)
1245 .SetSkipPointers(false)
1246 .SetSkipReferences(false)
1247 .SetHideItemNames(false);
1249 m_match_type
= eFormatterMatchExact
;
1251 m_python_script
= "";
1252 m_python_function
= "";
1253 m_format_string
= "";
1254 m_is_add_script
= false;
1255 m_category
= "default";
1258 #if LLDB_ENABLE_PYTHON
1260 bool CommandObjectTypeSummaryAdd::Execute_ScriptSummary(
1261 Args
&command
, CommandReturnObject
&result
) {
1262 const size_t argc
= command
.GetArgumentCount();
1264 if (argc
< 1 && !m_options
.m_name
) {
1265 result
.AppendErrorWithFormat("%s takes one or more args.\n",
1266 m_cmd_name
.c_str());
1270 TypeSummaryImplSP script_format
;
1272 if (!m_options
.m_python_function
1273 .empty()) // we have a Python function ready to use
1275 const char *funct_name
= m_options
.m_python_function
.c_str();
1276 if (!funct_name
|| !funct_name
[0]) {
1277 result
.AppendError("function name empty.\n");
1282 (" " + m_options
.m_python_function
+ "(valobj,internal_dict)");
1284 script_format
= std::make_shared
<ScriptSummaryFormat
>(
1285 m_options
.m_flags
, funct_name
, code
.c_str());
1287 ScriptInterpreter
*interpreter
= GetDebugger().GetScriptInterpreter();
1289 if (interpreter
&& !interpreter
->CheckObjectExists(funct_name
))
1290 result
.AppendWarningWithFormat(
1291 "The provided function \"%s\" does not exist - "
1292 "please define it before attempting to use this summary.\n",
1294 } else if (!m_options
.m_python_script
1295 .empty()) // we have a quick 1-line script, just use it
1297 ScriptInterpreter
*interpreter
= GetDebugger().GetScriptInterpreter();
1299 result
.AppendError("script interpreter missing - unable to generate "
1300 "function wrapper.\n");
1303 StringList funct_sl
;
1304 funct_sl
<< m_options
.m_python_script
.c_str();
1305 std::string funct_name_str
;
1306 if (!interpreter
->GenerateTypeScriptFunction(funct_sl
, funct_name_str
)) {
1307 result
.AppendError("unable to generate function wrapper.\n");
1310 if (funct_name_str
.empty()) {
1312 "script interpreter failed to generate a valid function name.\n");
1316 std::string code
= " " + m_options
.m_python_script
;
1318 script_format
= std::make_shared
<ScriptSummaryFormat
>(
1319 m_options
.m_flags
, funct_name_str
.c_str(), code
.c_str());
1321 // Use an IOHandler to grab Python code from the user
1322 auto options
= std::make_unique
<ScriptAddOptions
>(
1323 m_options
.m_flags
, m_options
.m_match_type
, m_options
.m_name
,
1324 m_options
.m_category
);
1326 for (auto &entry
: command
.entries()) {
1327 if (entry
.ref().empty()) {
1328 result
.AppendError("empty typenames not allowed");
1332 options
->m_target_types
<< std::string(entry
.ref());
1335 m_interpreter
.GetPythonCommandsFromIOHandler(
1337 *this, // IOHandlerDelegate
1338 options
.release()); // Baton for the "io_handler" that will be passed
1339 // back into our IOHandlerDelegate functions
1340 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
1342 return result
.Succeeded();
1345 // if I am here, script_format must point to something good, so I can add
1346 // that as a script summary to all interested parties
1350 for (auto &entry
: command
.entries()) {
1351 AddSummary(ConstString(entry
.ref()), script_format
, m_options
.m_match_type
,
1352 m_options
.m_category
, &error
);
1354 result
.AppendError(error
.AsCString());
1359 if (m_options
.m_name
) {
1360 AddNamedSummary(m_options
.m_name
, script_format
, &error
);
1362 result
.AppendError(error
.AsCString());
1363 result
.AppendError("added to types, but not given a name");
1368 return result
.Succeeded();
1373 bool CommandObjectTypeSummaryAdd::Execute_StringSummary(
1374 Args
&command
, CommandReturnObject
&result
) {
1375 const size_t argc
= command
.GetArgumentCount();
1377 if (argc
< 1 && !m_options
.m_name
) {
1378 result
.AppendErrorWithFormat("%s takes one or more args.\n",
1379 m_cmd_name
.c_str());
1383 if (!m_options
.m_flags
.GetShowMembersOneLiner() &&
1384 m_options
.m_format_string
.empty()) {
1385 result
.AppendError("empty summary strings not allowed");
1389 const char *format_cstr
= (m_options
.m_flags
.GetShowMembersOneLiner()
1391 : m_options
.m_format_string
.c_str());
1393 // ${var%S} is an endless recursion, prevent it
1394 if (strcmp(format_cstr
, "${var%S}") == 0) {
1395 result
.AppendError("recursive summary not allowed");
1399 std::unique_ptr
<StringSummaryFormat
> string_format(
1400 new StringSummaryFormat(m_options
.m_flags
, format_cstr
));
1401 if (!string_format
) {
1402 result
.AppendError("summary creation failed");
1405 if (string_format
->m_error
.Fail()) {
1406 result
.AppendErrorWithFormat("syntax error: %s",
1407 string_format
->m_error
.AsCString("<unknown>"));
1410 lldb::TypeSummaryImplSP
entry(string_format
.release());
1412 // now I have a valid format, let's add it to every type
1414 for (auto &arg_entry
: command
.entries()) {
1415 if (arg_entry
.ref().empty()) {
1416 result
.AppendError("empty typenames not allowed");
1419 ConstString
typeCS(arg_entry
.ref());
1421 AddSummary(typeCS
, entry
, m_options
.m_match_type
, m_options
.m_category
,
1425 result
.AppendError(error
.AsCString());
1430 if (m_options
.m_name
) {
1431 AddNamedSummary(m_options
.m_name
, entry
, &error
);
1433 result
.AppendError(error
.AsCString());
1434 result
.AppendError("added to types, but not given a name");
1439 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
1440 return result
.Succeeded();
1443 CommandObjectTypeSummaryAdd::CommandObjectTypeSummaryAdd(
1444 CommandInterpreter
&interpreter
)
1445 : CommandObjectParsed(interpreter
, "type summary add",
1446 "Add a new summary style for a type.", nullptr),
1447 IOHandlerDelegateMultiline("DONE"), m_options(interpreter
) {
1448 CommandArgumentEntry type_arg
;
1449 CommandArgumentData type_style_arg
;
1451 type_style_arg
.arg_type
= eArgTypeName
;
1452 type_style_arg
.arg_repetition
= eArgRepeatPlus
;
1454 type_arg
.push_back(type_style_arg
);
1456 m_arguments
.push_back(type_arg
);
1460 The following examples of 'type summary add' refer to this code snippet for context:
1466 JustADemo(int p = 1, float v = 0.1) : ptr(new int(p)), value(v) {}
1468 JustADemo demo_instance(42, 3.14);
1470 typedef JustADemo NewDemo;
1471 NewDemo new_demo_instance(42, 3.14);
1473 (lldb) type summary add --summary-string "the answer is $
{*var
.ptr
}" JustADemo
1475 Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is
42"
1477 (lldb) type summary add --summary-string "the answer is $
{*var
.ptr
}, and the question is $
{var
.value
}" JustADemo
1479 Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is
42 and the question is
3.14"
1482 "Alternatively, you could define formatting for all pointers to integers and \
1483 rely on that when formatting JustADemo to obtain the same result:"
1486 (lldb) type summary add --summary-string "$
{var
%V
} -> $
{*var
}" "int *"
1487 (lldb) type summary add --summary-string "the answer is $
{var
.ptr
}, and the question is $
{var
.value
}" JustADemo
1490 "Type summaries are automatically applied to derived typedefs, so the examples \
1491 above apply to both JustADemo and NewDemo. The cascade option can be used to \
1492 suppress this behavior:"
1495 (lldb) type summary add --summary-string "$
{var
.ptr
}, $
{var
.value
},{$
{var
.byte
}}" JustADemo -C no
1497 The summary will now be used for values of JustADemo but not NewDemo.
1500 "By default summaries are shown for pointers and references to values of the \
1501 specified type. To suppress formatting for pointers use the -p option, or apply \
1502 the corresponding -r option to suppress formatting for references:"
1505 (lldb) type summary add -p -r --summary-string "$
{var
.ptr
}, $
{var
.value
},{$
{var
.byte
}}" JustADemo
1508 "One-line summaries including all fields in a type can be inferred without supplying an \
1509 explicit summary string by passing the -c option:"
1512 (lldb) type summary add -c JustADemo
1513 (lldb) frame variable demo_instance
1514 (ptr=<address>, value=3.14)
1517 "Type summaries normally suppress the nested display of individual fields. To \
1518 supply a summary to supplement the default structure add the -e option:"
1521 (lldb) type summary add -e --summary-string "*ptr
= $
{*var
.ptr
}" JustADemo
1524 "Now when displaying JustADemo values the int* is displayed, followed by the \
1525 standard LLDB sequence of children, one per line:"
1534 "You can also add summaries written in Python. These scripts use lldb public API to \
1535 gather information from your variables and produce a meaningful summary. To start a \
1536 multi-line script use the -P option. The function declaration will be displayed along with \
1537 a comment describing the two arguments. End your script with the word 'DONE' on a line by \
1541 (lldb) type summary add JustADemo -P
1542 def function (valobj,internal_dict):
1543 """valobj
: an SBValue which you want to provide a summary
for
1544 internal_dict
: an LLDB support object
not to be used
"""
1545 value = valobj.GetChildMemberWithName('value');
1546 return 'My value is ' + value.GetValue();
1549 Alternatively, the -o option can be used when providing a simple one-line Python script:
1551 (lldb) type summary add JustADemo -o "value
= valobj
.GetChildMemberWithName('value'); return 'My value is ' + value
.GetValue();")");
1554 void CommandObjectTypeSummaryAdd::DoExecute(Args
&command
,
1555 CommandReturnObject
&result
) {
1556 WarnOnPotentialUnquotedUnsignedType(command
, result
);
1558 if (m_options
.m_is_add_script
) {
1559 #if LLDB_ENABLE_PYTHON
1560 Execute_ScriptSummary(command
, result
);
1562 result
.AppendError("python is disabled");
1567 Execute_StringSummary(command
, result
);
1570 static bool FixArrayTypeNameWithRegex(ConstString
&type_name
) {
1571 llvm::StringRef
type_name_ref(type_name
.GetStringRef());
1573 if (type_name_ref
.ends_with("[]")) {
1574 std::string
type_name_str(type_name
.GetCString());
1575 type_name_str
.resize(type_name_str
.length() - 2);
1576 if (type_name_str
.back() != ' ')
1577 type_name_str
.append(" ?\\[[0-9]+\\]");
1579 type_name_str
.append("\\[[0-9]+\\]");
1580 type_name
.SetCString(type_name_str
.c_str());
1586 bool CommandObjectTypeSummaryAdd::AddNamedSummary(ConstString summary_name
,
1587 TypeSummaryImplSP entry
,
1589 // system named summaries do not exist (yet?)
1590 DataVisualization::NamedSummaryFormats::Add(summary_name
, entry
);
1594 bool CommandObjectTypeSummaryAdd::AddSummary(ConstString type_name
,
1595 TypeSummaryImplSP entry
,
1596 FormatterMatchType match_type
,
1597 std::string category_name
,
1599 lldb::TypeCategoryImplSP category
;
1600 DataVisualization::Categories::GetCategory(ConstString(category_name
.c_str()),
1603 if (match_type
== eFormatterMatchExact
) {
1604 if (FixArrayTypeNameWithRegex(type_name
))
1605 match_type
= eFormatterMatchRegex
;
1608 if (match_type
== eFormatterMatchRegex
) {
1609 match_type
= eFormatterMatchRegex
;
1610 RegularExpression
typeRX(type_name
.GetStringRef());
1611 if (!typeRX
.IsValid()) {
1613 error
->SetErrorString(
1614 "regex format error (maybe this is not really a regex?)");
1619 if (match_type
== eFormatterMatchCallback
) {
1620 const char *function_name
= type_name
.AsCString();
1621 ScriptInterpreter
*interpreter
= GetDebugger().GetScriptInterpreter();
1622 if (interpreter
&& !interpreter
->CheckObjectExists(function_name
)) {
1623 error
->SetErrorStringWithFormat(
1624 "The provided recognizer function \"%s\" does not exist - "
1625 "please define it before attempting to use this summary.\n",
1630 category
->AddTypeSummary(type_name
.GetStringRef(), match_type
, entry
);
1634 // CommandObjectTypeSummaryDelete
1636 class CommandObjectTypeSummaryDelete
: public CommandObjectTypeFormatterDelete
{
1638 CommandObjectTypeSummaryDelete(CommandInterpreter
&interpreter
)
1639 : CommandObjectTypeFormatterDelete(
1640 interpreter
, eFormatCategoryItemSummary
) {}
1642 ~CommandObjectTypeSummaryDelete() override
= default;
1645 bool FormatterSpecificDeletion(ConstString typeCS
) override
{
1646 if (m_options
.m_language
!= lldb::eLanguageTypeUnknown
)
1648 return DataVisualization::NamedSummaryFormats::Delete(typeCS
);
1652 class CommandObjectTypeSummaryClear
: public CommandObjectTypeFormatterClear
{
1654 CommandObjectTypeSummaryClear(CommandInterpreter
&interpreter
)
1655 : CommandObjectTypeFormatterClear(interpreter
, eFormatCategoryItemSummary
,
1656 "type summary clear",
1657 "Delete all existing summaries.") {}
1660 void FormatterSpecificDeletion() override
{
1661 DataVisualization::NamedSummaryFormats::Clear();
1665 // CommandObjectTypeSummaryList
1667 class CommandObjectTypeSummaryList
1668 : public CommandObjectTypeFormatterList
<TypeSummaryImpl
> {
1670 CommandObjectTypeSummaryList(CommandInterpreter
&interpreter
)
1671 : CommandObjectTypeFormatterList(interpreter
, "type summary list",
1672 "Show a list of current summaries.") {}
1675 bool FormatterSpecificList(CommandReturnObject
&result
) override
{
1676 if (DataVisualization::NamedSummaryFormats::GetCount() > 0) {
1677 result
.GetOutputStream().Printf("Named summaries:\n");
1678 DataVisualization::NamedSummaryFormats::ForEach(
1679 [&result
](const TypeMatcher
&type_matcher
,
1680 const TypeSummaryImplSP
&summary_sp
) -> bool {
1681 result
.GetOutputStream().Printf(
1682 "%s: %s\n", type_matcher
.GetMatchString().GetCString(),
1683 summary_sp
->GetDescription().c_str());
1692 // CommandObjectTypeCategoryDefine
1693 #define LLDB_OPTIONS_type_category_define
1694 #include "CommandOptions.inc"
1696 class CommandObjectTypeCategoryDefine
: public CommandObjectParsed
{
1697 class CommandOptions
: public Options
{
1700 : m_define_enabled(false, false),
1701 m_cate_language(eLanguageTypeUnknown
, eLanguageTypeUnknown
) {}
1703 ~CommandOptions() override
= default;
1705 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
1706 ExecutionContext
*execution_context
) override
{
1708 const int short_option
= m_getopt_table
[option_idx
].val
;
1710 switch (short_option
) {
1712 m_define_enabled
.SetValueFromString(llvm::StringRef("true"));
1715 error
= m_cate_language
.SetValueFromString(option_arg
);
1718 llvm_unreachable("Unimplemented option");
1724 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
1725 m_define_enabled
.Clear();
1726 m_cate_language
.Clear();
1729 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
1730 return llvm::ArrayRef(g_type_category_define_options
);
1733 // Instance variables to hold the values for command options.
1735 OptionValueBoolean m_define_enabled
;
1736 OptionValueLanguage m_cate_language
;
1739 CommandOptions m_options
;
1741 Options
*GetOptions() override
{ return &m_options
; }
1744 CommandObjectTypeCategoryDefine(CommandInterpreter
&interpreter
)
1745 : CommandObjectParsed(interpreter
, "type category define",
1746 "Define a new category as a source of formatters.",
1748 CommandArgumentEntry type_arg
;
1749 CommandArgumentData type_style_arg
;
1751 type_style_arg
.arg_type
= eArgTypeName
;
1752 type_style_arg
.arg_repetition
= eArgRepeatPlus
;
1754 type_arg
.push_back(type_style_arg
);
1756 m_arguments
.push_back(type_arg
);
1759 ~CommandObjectTypeCategoryDefine() override
= default;
1762 HandleArgumentCompletion(CompletionRequest
&request
,
1763 OptionElementVector
&opt_element_vector
) override
{
1764 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1765 GetCommandInterpreter(), lldb::eTypeCategoryNameCompletion
, request
,
1770 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
1771 const size_t argc
= command
.GetArgumentCount();
1774 result
.AppendErrorWithFormat("%s takes 1 or more args.\n",
1775 m_cmd_name
.c_str());
1779 for (auto &entry
: command
.entries()) {
1780 TypeCategoryImplSP category_sp
;
1781 if (DataVisualization::Categories::GetCategory(ConstString(entry
.ref()),
1784 category_sp
->AddLanguage(m_options
.m_cate_language
.GetCurrentValue());
1785 if (m_options
.m_define_enabled
.GetCurrentValue())
1786 DataVisualization::Categories::Enable(category_sp
,
1787 TypeCategoryMap::Default
);
1791 result
.SetStatus(eReturnStatusSuccessFinishResult
);
1795 // CommandObjectTypeCategoryEnable
1796 #define LLDB_OPTIONS_type_category_enable
1797 #include "CommandOptions.inc"
1799 class CommandObjectTypeCategoryEnable
: public CommandObjectParsed
{
1800 class CommandOptions
: public Options
{
1802 CommandOptions() = default;
1804 ~CommandOptions() override
= default;
1806 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
1807 ExecutionContext
*execution_context
) override
{
1809 const int short_option
= m_getopt_table
[option_idx
].val
;
1811 switch (short_option
) {
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());
1821 llvm_unreachable("Unimplemented option");
1827 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
1828 m_language
= lldb::eLanguageTypeUnknown
;
1831 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
1832 return llvm::ArrayRef(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
; }
1845 CommandObjectTypeCategoryEnable(CommandInterpreter
&interpreter
)
1846 : CommandObjectParsed(interpreter
, "type category enable",
1847 "Enable a category as a source of formatters.",
1849 CommandArgumentEntry type_arg
;
1850 CommandArgumentData type_style_arg
;
1852 type_style_arg
.arg_type
= eArgTypeName
;
1853 type_style_arg
.arg_repetition
= eArgRepeatPlus
;
1855 type_arg
.push_back(type_style_arg
);
1857 m_arguments
.push_back(type_arg
);
1860 ~CommandObjectTypeCategoryEnable() override
= default;
1863 HandleArgumentCompletion(CompletionRequest
&request
,
1864 OptionElementVector
&opt_element_vector
) override
{
1865 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1866 GetCommandInterpreter(), lldb::eTypeCategoryNameCompletion
, request
,
1871 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
1872 const size_t argc
= command
.GetArgumentCount();
1874 if (argc
< 1 && m_options
.m_language
== lldb::eLanguageTypeUnknown
) {
1875 result
.AppendErrorWithFormat("%s takes arguments and/or a language",
1876 m_cmd_name
.c_str());
1880 if (argc
== 1 && strcmp(command
.GetArgumentAtIndex(0), "*") == 0) {
1881 DataVisualization::Categories::EnableStar();
1882 } else if (argc
> 0) {
1883 for (int i
= argc
- 1; i
>= 0; i
--) {
1884 const char *typeA
= command
.GetArgumentAtIndex(i
);
1885 ConstString
typeCS(typeA
);
1888 result
.AppendError("empty category name not allowed");
1891 DataVisualization::Categories::Enable(typeCS
);
1892 lldb::TypeCategoryImplSP cate
;
1893 if (DataVisualization::Categories::GetCategory(typeCS
, cate
) && cate
) {
1894 if (cate
->GetCount() == 0) {
1895 result
.AppendWarning("empty category enabled (typo?)");
1901 if (m_options
.m_language
!= lldb::eLanguageTypeUnknown
)
1902 DataVisualization::Categories::Enable(m_options
.m_language
);
1904 result
.SetStatus(eReturnStatusSuccessFinishResult
);
1908 // CommandObjectTypeCategoryDelete
1910 class CommandObjectTypeCategoryDelete
: public CommandObjectParsed
{
1912 CommandObjectTypeCategoryDelete(CommandInterpreter
&interpreter
)
1913 : CommandObjectParsed(interpreter
, "type category delete",
1914 "Delete a category and all associated formatters.",
1916 CommandArgumentEntry type_arg
;
1917 CommandArgumentData type_style_arg
;
1919 type_style_arg
.arg_type
= eArgTypeName
;
1920 type_style_arg
.arg_repetition
= eArgRepeatPlus
;
1922 type_arg
.push_back(type_style_arg
);
1924 m_arguments
.push_back(type_arg
);
1927 ~CommandObjectTypeCategoryDelete() override
= default;
1930 HandleArgumentCompletion(CompletionRequest
&request
,
1931 OptionElementVector
&opt_element_vector
) override
{
1932 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1933 GetCommandInterpreter(), lldb::eTypeCategoryNameCompletion
, request
,
1938 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
1939 const size_t argc
= command
.GetArgumentCount();
1942 result
.AppendErrorWithFormat("%s takes 1 or more arg.\n",
1943 m_cmd_name
.c_str());
1947 bool success
= true;
1949 // the order is not relevant here
1950 for (int i
= argc
- 1; i
>= 0; i
--) {
1951 const char *typeA
= command
.GetArgumentAtIndex(i
);
1952 ConstString
typeCS(typeA
);
1955 result
.AppendError("empty category name not allowed");
1958 if (!DataVisualization::Categories::Delete(typeCS
))
1959 success
= false; // keep deleting even if we hit an error
1962 result
.SetStatus(eReturnStatusSuccessFinishResult
);
1964 result
.AppendError("cannot delete one or more categories\n");
1969 // CommandObjectTypeCategoryDisable
1970 #define LLDB_OPTIONS_type_category_disable
1971 #include "CommandOptions.inc"
1973 class CommandObjectTypeCategoryDisable
: public CommandObjectParsed
{
1974 class CommandOptions
: public Options
{
1976 CommandOptions() = default;
1978 ~CommandOptions() override
= default;
1980 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
1981 ExecutionContext
*execution_context
) override
{
1983 const int short_option
= m_getopt_table
[option_idx
].val
;
1985 switch (short_option
) {
1987 if (!option_arg
.empty()) {
1988 m_language
= Language::GetLanguageTypeFromString(option_arg
);
1989 if (m_language
== lldb::eLanguageTypeUnknown
)
1990 error
.SetErrorStringWithFormat("unrecognized language '%s'",
1991 option_arg
.str().c_str());
1995 llvm_unreachable("Unimplemented option");
2001 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
2002 m_language
= lldb::eLanguageTypeUnknown
;
2005 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
2006 return llvm::ArrayRef(g_type_category_disable_options
);
2009 // Instance variables to hold the values for command options.
2011 lldb::LanguageType m_language
;
2014 CommandOptions m_options
;
2016 Options
*GetOptions() override
{ return &m_options
; }
2019 CommandObjectTypeCategoryDisable(CommandInterpreter
&interpreter
)
2020 : CommandObjectParsed(interpreter
, "type category disable",
2021 "Disable a category as a source of formatters.",
2023 CommandArgumentEntry type_arg
;
2024 CommandArgumentData type_style_arg
;
2026 type_style_arg
.arg_type
= eArgTypeName
;
2027 type_style_arg
.arg_repetition
= eArgRepeatPlus
;
2029 type_arg
.push_back(type_style_arg
);
2031 m_arguments
.push_back(type_arg
);
2034 ~CommandObjectTypeCategoryDisable() override
= default;
2037 HandleArgumentCompletion(CompletionRequest
&request
,
2038 OptionElementVector
&opt_element_vector
) override
{
2039 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
2040 GetCommandInterpreter(), lldb::eTypeCategoryNameCompletion
, request
,
2045 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
2046 const size_t argc
= command
.GetArgumentCount();
2048 if (argc
< 1 && m_options
.m_language
== lldb::eLanguageTypeUnknown
) {
2049 result
.AppendErrorWithFormat("%s takes arguments and/or a language",
2050 m_cmd_name
.c_str());
2054 if (argc
== 1 && strcmp(command
.GetArgumentAtIndex(0), "*") == 0) {
2055 DataVisualization::Categories::DisableStar();
2056 } else if (argc
> 0) {
2057 // the order is not relevant here
2058 for (int i
= argc
- 1; i
>= 0; i
--) {
2059 const char *typeA
= command
.GetArgumentAtIndex(i
);
2060 ConstString
typeCS(typeA
);
2063 result
.AppendError("empty category name not allowed");
2066 DataVisualization::Categories::Disable(typeCS
);
2070 if (m_options
.m_language
!= lldb::eLanguageTypeUnknown
)
2071 DataVisualization::Categories::Disable(m_options
.m_language
);
2073 result
.SetStatus(eReturnStatusSuccessFinishResult
);
2077 // CommandObjectTypeCategoryList
2079 class CommandObjectTypeCategoryList
: public CommandObjectParsed
{
2081 CommandObjectTypeCategoryList(CommandInterpreter
&interpreter
)
2082 : CommandObjectParsed(interpreter
, "type category list",
2083 "Provide a list of all existing categories.",
2085 CommandArgumentEntry type_arg
;
2086 CommandArgumentData type_style_arg
;
2088 type_style_arg
.arg_type
= eArgTypeName
;
2089 type_style_arg
.arg_repetition
= eArgRepeatOptional
;
2091 type_arg
.push_back(type_style_arg
);
2093 m_arguments
.push_back(type_arg
);
2096 ~CommandObjectTypeCategoryList() override
= default;
2099 HandleArgumentCompletion(CompletionRequest
&request
,
2100 OptionElementVector
&opt_element_vector
) override
{
2101 if (request
.GetCursorIndex())
2103 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
2104 GetCommandInterpreter(), lldb::eTypeCategoryNameCompletion
, request
,
2109 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
2110 const size_t argc
= command
.GetArgumentCount();
2112 std::unique_ptr
<RegularExpression
> regex
;
2115 const char *arg
= command
.GetArgumentAtIndex(0);
2116 regex
= std::make_unique
<RegularExpression
>(arg
);
2117 if (!regex
->IsValid()) {
2118 result
.AppendErrorWithFormat(
2119 "syntax error in category regular expression '%s'", arg
);
2122 } else if (argc
!= 0) {
2123 result
.AppendErrorWithFormat("%s takes 0 or one arg.\n",
2124 m_cmd_name
.c_str());
2128 DataVisualization::Categories::ForEach(
2129 [®ex
, &result
](const lldb::TypeCategoryImplSP
&category_sp
) -> bool {
2132 if (regex
->GetText() == category_sp
->GetName()) {
2134 } else if (regex
->Execute(category_sp
->GetName())) {
2142 result
.GetOutputStream().Printf(
2143 "Category: %s\n", category_sp
->GetDescription().c_str());
2148 result
.SetStatus(eReturnStatusSuccessFinishResult
);
2152 // CommandObjectTypeFilterList
2154 class CommandObjectTypeFilterList
2155 : public CommandObjectTypeFormatterList
<TypeFilterImpl
> {
2157 CommandObjectTypeFilterList(CommandInterpreter
&interpreter
)
2158 : CommandObjectTypeFormatterList(interpreter
, "type filter list",
2159 "Show a list of current filters.") {}
2162 // CommandObjectTypeSynthList
2164 class CommandObjectTypeSynthList
2165 : public CommandObjectTypeFormatterList
<SyntheticChildren
> {
2167 CommandObjectTypeSynthList(CommandInterpreter
&interpreter
)
2168 : CommandObjectTypeFormatterList(
2169 interpreter
, "type synthetic list",
2170 "Show a list of current synthetic providers.") {}
2173 // CommandObjectTypeFilterDelete
2175 class CommandObjectTypeFilterDelete
: public CommandObjectTypeFormatterDelete
{
2177 CommandObjectTypeFilterDelete(CommandInterpreter
&interpreter
)
2178 : CommandObjectTypeFormatterDelete(
2179 interpreter
, eFormatCategoryItemFilter
) {}
2181 ~CommandObjectTypeFilterDelete() override
= default;
2184 // CommandObjectTypeSynthDelete
2186 class CommandObjectTypeSynthDelete
: public CommandObjectTypeFormatterDelete
{
2188 CommandObjectTypeSynthDelete(CommandInterpreter
&interpreter
)
2189 : CommandObjectTypeFormatterDelete(
2190 interpreter
, eFormatCategoryItemSynth
) {}
2192 ~CommandObjectTypeSynthDelete() override
= default;
2196 // CommandObjectTypeFilterClear
2198 class CommandObjectTypeFilterClear
: public CommandObjectTypeFormatterClear
{
2200 CommandObjectTypeFilterClear(CommandInterpreter
&interpreter
)
2201 : CommandObjectTypeFormatterClear(interpreter
, eFormatCategoryItemFilter
,
2202 "type filter clear",
2203 "Delete all existing filter.") {}
2206 // CommandObjectTypeSynthClear
2208 class CommandObjectTypeSynthClear
: public CommandObjectTypeFormatterClear
{
2210 CommandObjectTypeSynthClear(CommandInterpreter
&interpreter
)
2211 : CommandObjectTypeFormatterClear(
2212 interpreter
, eFormatCategoryItemSynth
, "type synthetic clear",
2213 "Delete all existing synthetic providers.") {}
2216 bool CommandObjectTypeSynthAdd::Execute_HandwritePython(
2217 Args
&command
, CommandReturnObject
&result
) {
2218 auto options
= std::make_unique
<SynthAddOptions
>(
2219 m_options
.m_skip_pointers
, m_options
.m_skip_references
,
2220 m_options
.m_cascade
, m_options
.m_match_type
, m_options
.m_category
);
2222 for (auto &entry
: command
.entries()) {
2223 if (entry
.ref().empty()) {
2224 result
.AppendError("empty typenames not allowed");
2228 options
->m_target_types
<< std::string(entry
.ref());
2231 m_interpreter
.GetPythonCommandsFromIOHandler(
2233 *this, // IOHandlerDelegate
2234 options
.release()); // Baton for the "io_handler" that will be passed back
2235 // into our 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();
2245 result
.AppendErrorWithFormat("%s takes one or more args.\n",
2246 m_cmd_name
.c_str());
2250 if (m_options
.m_class_name
.empty() && !m_options
.m_input_python
) {
2251 result
.AppendErrorWithFormat("%s needs either a Python class name or -P to "
2252 "directly input Python code.\n",
2253 m_cmd_name
.c_str());
2257 SyntheticChildrenSP entry
;
2259 ScriptedSyntheticChildren
*impl
= new ScriptedSyntheticChildren(
2260 SyntheticChildren::Flags()
2261 .SetCascades(m_options
.m_cascade
)
2262 .SetSkipPointers(m_options
.m_skip_pointers
)
2263 .SetSkipReferences(m_options
.m_skip_references
),
2264 m_options
.m_class_name
.c_str());
2268 ScriptInterpreter
*interpreter
= GetDebugger().GetScriptInterpreter();
2271 !interpreter
->CheckObjectExists(impl
->GetPythonClassName()))
2272 result
.AppendWarning("The provided class does not exist - please define it "
2273 "before attempting to use this synthetic provider");
2275 // now I have a valid provider, let's add it to every type
2277 lldb::TypeCategoryImplSP category
;
2278 DataVisualization::Categories::GetCategory(
2279 ConstString(m_options
.m_category
.c_str()), category
);
2283 for (auto &arg_entry
: command
.entries()) {
2284 if (arg_entry
.ref().empty()) {
2285 result
.AppendError("empty typenames not allowed");
2289 ConstString
typeCS(arg_entry
.ref());
2290 if (!AddSynth(typeCS
, entry
, m_options
.m_match_type
, m_options
.m_category
,
2292 result
.AppendError(error
.AsCString());
2297 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
2298 return result
.Succeeded();
2301 CommandObjectTypeSynthAdd::CommandObjectTypeSynthAdd(
2302 CommandInterpreter
&interpreter
)
2303 : CommandObjectParsed(interpreter
, "type synthetic add",
2304 "Add a new synthetic provider for a type.", nullptr),
2305 IOHandlerDelegateMultiline("DONE"), m_options() {
2306 CommandArgumentEntry type_arg
;
2307 CommandArgumentData type_style_arg
;
2309 type_style_arg
.arg_type
= eArgTypeName
;
2310 type_style_arg
.arg_repetition
= eArgRepeatPlus
;
2312 type_arg
.push_back(type_style_arg
);
2314 m_arguments
.push_back(type_arg
);
2317 bool CommandObjectTypeSynthAdd::AddSynth(ConstString type_name
,
2318 SyntheticChildrenSP entry
,
2319 FormatterMatchType match_type
,
2320 std::string category_name
,
2322 lldb::TypeCategoryImplSP category
;
2323 DataVisualization::Categories::GetCategory(ConstString(category_name
.c_str()),
2326 if (match_type
== eFormatterMatchExact
) {
2327 if (FixArrayTypeNameWithRegex(type_name
))
2328 match_type
= eFormatterMatchRegex
;
2331 // Only check for conflicting filters in the same category if `type_name` is
2332 // an actual type name. Matching a regex string against registered regexes
2334 if (match_type
== eFormatterMatchExact
) {
2335 // It's not generally possible to get a type object here. For example, this
2336 // command can be run before loading any binaries. Do just a best-effort
2337 // name-based lookup here to try to prevent conflicts.
2338 FormattersMatchCandidate
candidate_type(type_name
, nullptr, TypeImpl(),
2339 FormattersMatchCandidate::Flags());
2340 if (category
->AnyMatches(candidate_type
, eFormatCategoryItemFilter
,
2343 error
->SetErrorStringWithFormat("cannot add synthetic for type %s when "
2344 "filter is defined in same category!",
2345 type_name
.AsCString());
2350 if (match_type
== eFormatterMatchRegex
) {
2351 RegularExpression
typeRX(type_name
.GetStringRef());
2352 if (!typeRX
.IsValid()) {
2354 error
->SetErrorString(
2355 "regex format error (maybe this is not really a regex?)");
2360 if (match_type
== eFormatterMatchCallback
) {
2361 const char *function_name
= type_name
.AsCString();
2362 ScriptInterpreter
*interpreter
= GetDebugger().GetScriptInterpreter();
2363 if (interpreter
&& !interpreter
->CheckObjectExists(function_name
)) {
2364 error
->SetErrorStringWithFormat(
2365 "The provided recognizer function \"%s\" does not exist - "
2366 "please define it before attempting to use this summary.\n",
2372 category
->AddTypeSynthetic(type_name
.GetStringRef(), match_type
, entry
);
2376 #define LLDB_OPTIONS_type_filter_add
2377 #include "CommandOptions.inc"
2379 class CommandObjectTypeFilterAdd
: public CommandObjectParsed
{
2381 class CommandOptions
: public Options
{
2382 typedef std::vector
<std::string
> option_vector
;
2385 CommandOptions() = default;
2387 ~CommandOptions() override
= default;
2389 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
2390 ExecutionContext
*execution_context
) override
{
2392 const int short_option
= m_getopt_table
[option_idx
].val
;
2395 switch (short_option
) {
2397 m_cascade
= OptionArgParser::ToBoolean(option_arg
, true, &success
);
2399 error
.SetErrorStringWithFormat("invalid value for cascade: %s",
2400 option_arg
.str().c_str());
2403 m_expr_paths
.push_back(std::string(option_arg
));
2404 has_child_list
= true;
2407 m_skip_pointers
= true;
2410 m_skip_references
= true;
2413 m_category
= std::string(option_arg
);
2419 llvm_unreachable("Unimplemented option");
2425 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
2427 m_skip_pointers
= false;
2428 m_skip_references
= false;
2429 m_category
= "default";
2430 m_expr_paths
.clear();
2431 has_child_list
= false;
2435 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
2436 return llvm::ArrayRef(g_type_filter_add_options
);
2439 // Instance variables to hold the values for command options.
2442 bool m_skip_references
;
2443 bool m_skip_pointers
;
2444 bool m_input_python
;
2445 option_vector m_expr_paths
;
2446 std::string m_category
;
2447 bool has_child_list
;
2450 typedef option_vector::iterator ExpressionPathsIterator
;
2453 CommandOptions m_options
;
2455 Options
*GetOptions() override
{ return &m_options
; }
2457 enum FilterFormatType
{ eRegularFilter
, eRegexFilter
};
2459 bool AddFilter(ConstString type_name
, TypeFilterImplSP entry
,
2460 FilterFormatType type
, std::string category_name
,
2462 lldb::TypeCategoryImplSP category
;
2463 DataVisualization::Categories::GetCategory(
2464 ConstString(category_name
.c_str()), category
);
2466 if (type
== eRegularFilter
) {
2467 if (FixArrayTypeNameWithRegex(type_name
))
2468 type
= eRegexFilter
;
2471 // Only check for conflicting synthetic child providers in the same category
2472 // if `type_name` is an actual type name. Matching a regex string against
2473 // registered regexes doesn't work.
2474 if (type
== eRegularFilter
) {
2475 // It's not generally possible to get a type object here. For example,
2476 // this command can be run before loading any binaries. Do just a
2477 // best-effort name-based lookup here to try to prevent conflicts.
2478 FormattersMatchCandidate
candidate_type(
2479 type_name
, nullptr, TypeImpl(), FormattersMatchCandidate::Flags());
2480 lldb::SyntheticChildrenSP entry
;
2481 if (category
->AnyMatches(candidate_type
, eFormatCategoryItemSynth
,
2484 error
->SetErrorStringWithFormat("cannot add filter for type %s when "
2485 "synthetic is defined in same "
2487 type_name
.AsCString());
2492 FormatterMatchType match_type
= eFormatterMatchExact
;
2493 if (type
== eRegexFilter
) {
2494 match_type
= eFormatterMatchRegex
;
2495 RegularExpression
typeRX(type_name
.GetStringRef());
2496 if (!typeRX
.IsValid()) {
2498 error
->SetErrorString(
2499 "regex format error (maybe this is not really a regex?)");
2503 category
->AddTypeFilter(type_name
.GetStringRef(), match_type
, entry
);
2508 CommandObjectTypeFilterAdd(CommandInterpreter
&interpreter
)
2509 : CommandObjectParsed(interpreter
, "type filter add",
2510 "Add a new filter for a type.", nullptr) {
2511 CommandArgumentEntry type_arg
;
2512 CommandArgumentData type_style_arg
;
2514 type_style_arg
.arg_type
= eArgTypeName
;
2515 type_style_arg
.arg_repetition
= eArgRepeatPlus
;
2517 type_arg
.push_back(type_style_arg
);
2519 m_arguments
.push_back(type_arg
);
2523 The following examples of 'type filter add' refer to this code snippet for context:
2538 Adding a simple filter:
2540 (lldb) type filter add --child a --child g Foo
2541 (lldb) frame variable my_foo
2544 "Produces output where only a and g are displayed. Other children of my_foo \
2545 (b, c, d, e, f, h and i) are available by asking for them explicitly:"
2548 (lldb) frame variable my_foo.b my_foo.c my_foo.i
2551 "The formatting option --raw on frame variable bypasses the filter, showing \
2552 all children of my_foo as if no filter was defined:"
2555 (lldb) frame variable my_foo --raw)");
2558 ~CommandObjectTypeFilterAdd() override
= default;
2561 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
2562 const size_t argc
= command
.GetArgumentCount();
2565 result
.AppendErrorWithFormat("%s takes one or more args.\n",
2566 m_cmd_name
.c_str());
2570 if (m_options
.m_expr_paths
.empty()) {
2571 result
.AppendErrorWithFormat("%s needs one or more children.\n",
2572 m_cmd_name
.c_str());
2576 TypeFilterImplSP
entry(new TypeFilterImpl(
2577 SyntheticChildren::Flags()
2578 .SetCascades(m_options
.m_cascade
)
2579 .SetSkipPointers(m_options
.m_skip_pointers
)
2580 .SetSkipReferences(m_options
.m_skip_references
)));
2582 // go through the expression paths
2583 CommandOptions::ExpressionPathsIterator begin
,
2584 end
= m_options
.m_expr_paths
.end();
2586 for (begin
= m_options
.m_expr_paths
.begin(); begin
!= end
; begin
++)
2587 entry
->AddExpressionPath(*begin
);
2589 // now I have a valid provider, let's add it to every type
2591 lldb::TypeCategoryImplSP category
;
2592 DataVisualization::Categories::GetCategory(
2593 ConstString(m_options
.m_category
.c_str()), category
);
2597 WarnOnPotentialUnquotedUnsignedType(command
, result
);
2599 for (auto &arg_entry
: command
.entries()) {
2600 if (arg_entry
.ref().empty()) {
2601 result
.AppendError("empty typenames not allowed");
2605 ConstString
typeCS(arg_entry
.ref());
2606 if (!AddFilter(typeCS
, entry
,
2607 m_options
.m_regex
? eRegexFilter
: eRegularFilter
,
2608 m_options
.m_category
, &error
)) {
2609 result
.AppendError(error
.AsCString());
2614 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
2619 #define LLDB_OPTIONS_type_lookup
2620 #include "CommandOptions.inc"
2622 class CommandObjectTypeLookup
: public CommandObjectRaw
{
2624 // this function is allowed to do a more aggressive job at guessing languages
2625 // than the expression parser is comfortable with - so leave the original
2626 // call alone and add one that is specific to type lookup
2627 lldb::LanguageType
GuessLanguage(StackFrame
*frame
) {
2628 lldb::LanguageType lang_type
= lldb::eLanguageTypeUnknown
;
2633 lang_type
= frame
->GuessLanguage();
2634 if (lang_type
!= lldb::eLanguageTypeUnknown
)
2637 Symbol
*s
= frame
->GetSymbolContext(eSymbolContextSymbol
).symbol
;
2639 lang_type
= s
->GetMangled().GuessLanguage();
2644 class CommandOptions
: public OptionGroup
{
2646 CommandOptions() = default;
2648 ~CommandOptions() override
= default;
2650 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
2651 return llvm::ArrayRef(g_type_lookup_options
);
2654 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_value
,
2655 ExecutionContext
*execution_context
) override
{
2658 const int short_option
= g_type_lookup_options
[option_idx
].short_option
;
2660 switch (short_option
) {
2666 m_language
= Language::GetLanguageTypeFromString(option_value
);
2670 llvm_unreachable("Unimplemented option");
2676 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
2677 m_show_help
= false;
2678 m_language
= eLanguageTypeUnknown
;
2681 // Options table: Required for subclasses of Options.
2683 bool m_show_help
= false;
2684 lldb::LanguageType m_language
= eLanguageTypeUnknown
;
2687 OptionGroupOptions m_option_group
;
2688 CommandOptions m_command_options
;
2691 CommandObjectTypeLookup(CommandInterpreter
&interpreter
)
2692 : CommandObjectRaw(interpreter
, "type lookup",
2693 "Lookup types and declarations in the current target, "
2694 "following language-specific naming conventions.",
2695 "type lookup <type-specifier>",
2696 eCommandRequiresTarget
) {
2697 m_option_group
.Append(&m_command_options
);
2698 m_option_group
.Finalize();
2701 ~CommandObjectTypeLookup() override
= default;
2703 Options
*GetOptions() override
{ return &m_option_group
; }
2705 llvm::StringRef
GetHelpLong() override
{
2706 if (!m_cmd_help_long
.empty())
2707 return m_cmd_help_long
;
2709 StreamString stream
;
2710 Language::ForEach([&](Language
*lang
) {
2711 if (const char *help
= lang
->GetLanguageSpecificTypeLookupHelp())
2712 stream
.Printf("%s\n", help
);
2716 m_cmd_help_long
= std::string(stream
.GetString());
2717 return m_cmd_help_long
;
2720 void DoExecute(llvm::StringRef raw_command_line
,
2721 CommandReturnObject
&result
) override
{
2722 if (raw_command_line
.empty()) {
2724 "type lookup cannot be invoked without a type name as argument");
2728 auto exe_ctx
= GetCommandInterpreter().GetExecutionContext();
2729 m_option_group
.NotifyOptionParsingStarting(&exe_ctx
);
2731 OptionsWithRaw
args(raw_command_line
);
2732 const char *name_of_type
= args
.GetRawPart().c_str();
2735 if (!ParseOptionsAndNotify(args
.GetArgs(), result
, m_option_group
,
2739 ExecutionContextScope
*best_scope
= exe_ctx
.GetBestExecutionContextScope();
2741 bool any_found
= false;
2743 std::vector
<Language
*> languages
;
2745 bool is_global_search
= false;
2746 LanguageType guessed_language
= lldb::eLanguageTypeUnknown
;
2748 if ((is_global_search
=
2749 (m_command_options
.m_language
== eLanguageTypeUnknown
))) {
2750 Language::ForEach([&](Language
*lang
) {
2751 languages
.push_back(lang
);
2755 languages
.push_back(Language::FindPlugin(m_command_options
.m_language
));
2758 // This is not the most efficient way to do this, but we support very few
2759 // languages so the cost of the sort is going to be dwarfed by the actual
2761 if (StackFrame
*frame
= m_exe_ctx
.GetFramePtr()) {
2762 guessed_language
= GuessLanguage(frame
);
2763 if (guessed_language
!= eLanguageTypeUnknown
) {
2765 languages
.begin(), languages
.end(),
2766 [guessed_language
](Language
*lang1
, Language
*lang2
) -> bool {
2767 if (!lang1
|| !lang2
)
2769 LanguageType lt1
= lang1
->GetLanguageType();
2770 LanguageType lt2
= lang2
->GetLanguageType();
2771 if (lt1
== guessed_language
)
2772 return true; // make the selected frame's language come first
2773 if (lt2
== guessed_language
)
2774 return false; // make the selected frame's language come first
2775 return (lt1
< lt2
); // normal comparison otherwise
2780 bool is_first_language
= true;
2782 for (Language
*language
: languages
) {
2786 if (auto scavenger
= language
->GetTypeScavenger()) {
2787 Language::TypeScavenger::ResultSet search_results
;
2788 if (scavenger
->Find(best_scope
, name_of_type
, search_results
) > 0) {
2789 for (const auto &search_result
: search_results
) {
2790 if (search_result
&& search_result
->IsValid()) {
2792 search_result
->DumpToStream(result
.GetOutputStream(),
2793 this->m_command_options
.m_show_help
);
2798 // this is "type lookup SomeName" and we did find a match, so get out
2799 if (any_found
&& is_global_search
)
2801 else if (is_first_language
&& is_global_search
&&
2802 guessed_language
!= lldb::eLanguageTypeUnknown
) {
2803 is_first_language
= false;
2804 result
.GetOutputStream().Printf(
2805 "no type was found in the current language %s matching '%s'; "
2806 "performing a global search across all languages\n",
2807 Language::GetNameForLanguageType(guessed_language
), name_of_type
);
2812 result
.AppendMessageWithFormat("no type was found matching '%s'\n",
2815 result
.SetStatus(any_found
? lldb::eReturnStatusSuccessFinishResult
2816 : lldb::eReturnStatusSuccessFinishNoResult
);
2820 template <typename FormatterType
>
2821 class CommandObjectFormatterInfo
: public CommandObjectRaw
{
2823 typedef std::function
<typename
FormatterType::SharedPointer(ValueObject
&)>
2825 CommandObjectFormatterInfo(CommandInterpreter
&interpreter
,
2826 const char *formatter_name
,
2827 DiscoveryFunction discovery_func
)
2828 : CommandObjectRaw(interpreter
, "", "", "", eCommandRequiresFrame
),
2829 m_formatter_name(formatter_name
? formatter_name
: ""),
2830 m_discovery_function(discovery_func
) {
2832 name
.Printf("type %s info", formatter_name
);
2833 SetCommandName(name
.GetString());
2835 help
.Printf("This command evaluates the provided expression and shows "
2836 "which %s is applied to the resulting value (if any).",
2838 SetHelp(help
.GetString());
2839 StreamString syntax
;
2840 syntax
.Printf("type %s info <expr>", formatter_name
);
2841 SetSyntax(syntax
.GetString());
2844 ~CommandObjectFormatterInfo() override
= default;
2847 void DoExecute(llvm::StringRef command
,
2848 CommandReturnObject
&result
) override
{
2849 TargetSP target_sp
= GetDebugger().GetSelectedTarget();
2850 Thread
*thread
= GetDefaultThread();
2852 result
.AppendError("no default thread");
2856 StackFrameSP frame_sp
=
2857 thread
->GetSelectedFrame(DoNoSelectMostRelevantFrame
);
2858 ValueObjectSP result_valobj_sp
;
2859 EvaluateExpressionOptions options
;
2860 lldb::ExpressionResults expr_result
= target_sp
->EvaluateExpression(
2861 command
, frame_sp
.get(), result_valobj_sp
, options
);
2862 if (expr_result
== eExpressionCompleted
&& result_valobj_sp
) {
2864 result_valobj_sp
->GetQualifiedRepresentationIfAvailable(
2865 target_sp
->GetPreferDynamicValue(),
2866 target_sp
->GetEnableSyntheticValue());
2867 typename
FormatterType::SharedPointer formatter_sp
=
2868 m_discovery_function(*result_valobj_sp
);
2870 std::string
description(formatter_sp
->GetDescription());
2871 result
.GetOutputStream()
2872 << m_formatter_name
<< " applied to ("
2873 << result_valobj_sp
->GetDisplayTypeName().AsCString("<unknown>")
2874 << ") " << command
<< " is: " << description
<< "\n";
2875 result
.SetStatus(lldb::eReturnStatusSuccessFinishResult
);
2877 result
.GetOutputStream()
2878 << "no " << m_formatter_name
<< " applies to ("
2879 << result_valobj_sp
->GetDisplayTypeName().AsCString("<unknown>")
2880 << ") " << command
<< "\n";
2881 result
.SetStatus(lldb::eReturnStatusSuccessFinishNoResult
);
2884 result
.AppendError("failed to evaluate expression");
2889 std::string m_formatter_name
;
2890 DiscoveryFunction m_discovery_function
;
2893 class CommandObjectTypeFormat
: public CommandObjectMultiword
{
2895 CommandObjectTypeFormat(CommandInterpreter
&interpreter
)
2896 : CommandObjectMultiword(
2897 interpreter
, "type format",
2898 "Commands for customizing value display formats.",
2899 "type format [<sub-command-options>] ") {
2901 "add", CommandObjectSP(new CommandObjectTypeFormatAdd(interpreter
)));
2902 LoadSubCommand("clear", CommandObjectSP(
2903 new CommandObjectTypeFormatClear(interpreter
)));
2904 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFormatDelete(
2907 "list", CommandObjectSP(new CommandObjectTypeFormatList(interpreter
)));
2909 "info", CommandObjectSP(new CommandObjectFormatterInfo
<TypeFormatImpl
>(
2910 interpreter
, "format",
2911 [](ValueObject
&valobj
) -> TypeFormatImpl::SharedPointer
{
2912 return valobj
.GetValueFormat();
2916 ~CommandObjectTypeFormat() override
= default;
2919 class CommandObjectTypeSynth
: public CommandObjectMultiword
{
2921 CommandObjectTypeSynth(CommandInterpreter
&interpreter
)
2922 : CommandObjectMultiword(
2923 interpreter
, "type synthetic",
2924 "Commands for operating on synthetic type representations.",
2925 "type synthetic [<sub-command-options>] ") {
2926 LoadSubCommand("add",
2927 CommandObjectSP(new CommandObjectTypeSynthAdd(interpreter
)));
2929 "clear", CommandObjectSP(new CommandObjectTypeSynthClear(interpreter
)));
2930 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSynthDelete(
2933 "list", CommandObjectSP(new CommandObjectTypeSynthList(interpreter
)));
2936 CommandObjectSP(new CommandObjectFormatterInfo
<SyntheticChildren
>(
2937 interpreter
, "synthetic",
2938 [](ValueObject
&valobj
) -> SyntheticChildren::SharedPointer
{
2939 return valobj
.GetSyntheticChildren();
2943 ~CommandObjectTypeSynth() override
= default;
2946 class CommandObjectTypeFilter
: public CommandObjectMultiword
{
2948 CommandObjectTypeFilter(CommandInterpreter
&interpreter
)
2949 : CommandObjectMultiword(interpreter
, "type filter",
2950 "Commands for operating on type filters.",
2951 "type filter [<sub-command-options>] ") {
2953 "add", CommandObjectSP(new CommandObjectTypeFilterAdd(interpreter
)));
2954 LoadSubCommand("clear", CommandObjectSP(
2955 new CommandObjectTypeFilterClear(interpreter
)));
2956 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFilterDelete(
2959 "list", CommandObjectSP(new CommandObjectTypeFilterList(interpreter
)));
2962 ~CommandObjectTypeFilter() override
= default;
2965 class CommandObjectTypeCategory
: public CommandObjectMultiword
{
2967 CommandObjectTypeCategory(CommandInterpreter
&interpreter
)
2968 : CommandObjectMultiword(interpreter
, "type category",
2969 "Commands for operating on type categories.",
2970 "type category [<sub-command-options>] ") {
2973 CommandObjectSP(new CommandObjectTypeCategoryDefine(interpreter
)));
2976 CommandObjectSP(new CommandObjectTypeCategoryEnable(interpreter
)));
2979 CommandObjectSP(new CommandObjectTypeCategoryDisable(interpreter
)));
2982 CommandObjectSP(new CommandObjectTypeCategoryDelete(interpreter
)));
2983 LoadSubCommand("list", CommandObjectSP(
2984 new CommandObjectTypeCategoryList(interpreter
)));
2987 ~CommandObjectTypeCategory() override
= default;
2990 class CommandObjectTypeSummary
: public CommandObjectMultiword
{
2992 CommandObjectTypeSummary(CommandInterpreter
&interpreter
)
2993 : CommandObjectMultiword(
2994 interpreter
, "type summary",
2995 "Commands for editing variable summary display options.",
2996 "type summary [<sub-command-options>] ") {
2998 "add", CommandObjectSP(new CommandObjectTypeSummaryAdd(interpreter
)));
2999 LoadSubCommand("clear", CommandObjectSP(new CommandObjectTypeSummaryClear(
3001 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSummaryDelete(
3004 "list", CommandObjectSP(new CommandObjectTypeSummaryList(interpreter
)));
3006 "info", CommandObjectSP(new CommandObjectFormatterInfo
<TypeSummaryImpl
>(
3007 interpreter
, "summary",
3008 [](ValueObject
&valobj
) -> TypeSummaryImpl::SharedPointer
{
3009 return valobj
.GetSummaryFormat();
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 LoadSubCommand("synthetic",
3031 CommandObjectSP(new CommandObjectTypeSynth(interpreter
)));
3032 LoadSubCommand("lookup",
3033 CommandObjectSP(new CommandObjectTypeLookup(interpreter
)));
3036 CommandObjectType::~CommandObjectType() = default;