1 //===-- CommandObjectType.cpp ---------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "CommandObjectType.h"
10 
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"
35 
36 #include "llvm/ADT/STLExtras.h"
37 
38 #include <algorithm>
39 #include <functional>
40 #include <memory>
41 
42 using namespace lldb;
43 using namespace lldb_private;
44 
45 class ScriptAddOptions {
46 public:
47   TypeSummaryImpl::Flags m_flags;
48   StringList m_target_types;
49   FormatterMatchType m_match_type;
50   ConstString m_name;
51   std::string m_category;
52 
53   ScriptAddOptions(const TypeSummaryImpl::Flags &flags,
54                    FormatterMatchType match_type, ConstString name,
55                    std::string catg)
56       : m_flags(flags), m_match_type(match_type), m_name(name),
57         m_category(catg) {}
58 
59   typedef std::shared_ptr<ScriptAddOptions> SharedPointer;
60 };
61 
62 class SynthAddOptions {
63 public:
64   bool m_skip_pointers;
65   bool m_skip_references;
66   bool m_cascade;
67   FormatterMatchType m_match_type;
68   StringList m_target_types;
69   std::string m_category;
70 
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) {}
75 
76   typedef std::shared_ptr<SynthAddOptions> SharedPointer;
77 };
78 
79 static bool WarnOnPotentialUnquotedUnsignedType(Args &command,
80                                                 CommandReturnObject &result) {
81   if (command.empty())
82     return false;
83 
84   for (auto entry : llvm::enumerate(command.entries().drop_back())) {
85     if (entry.value().ref() != "unsigned")
86       continue;
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 "
91           "type "
92           "name use  quotes, as in \"unsigned %s\"\n",
93           next.str().c_str(), next.str().c_str());
94       return true;
95     }
96   }
97   return false;
98 }
99 
100 const char *FormatCategoryToString(FormatCategoryItem item, bool long_name) {
101   switch (item) {
102   case eFormatCategoryItemSummary:
103     return "summary";
104   case eFormatCategoryItemFilter:
105     return "filter";
106   case eFormatCategoryItemSynth:
107     if (long_name)
108       return "synthetic child provider";
109     return "synthetic";
110   case eFormatCategoryItemFormat:
111     return "format";
112   }
113   llvm_unreachable("Fully covered switch above!");
114 }
115 
116 #define LLDB_OPTIONS_type_summary_add
117 #include "CommandOptions.inc"
118 
119 class CommandObjectTypeSummaryAdd : public CommandObjectParsed,
120                                     public IOHandlerDelegateMultiline {
121 private:
122   class CommandOptions : public Options {
123   public:
124     CommandOptions(CommandInterpreter &interpreter) {}
125 
126     ~CommandOptions() override = default;
127 
128     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
129                           ExecutionContext *execution_context) override;
130 
131     void OptionParsingStarting(ExecutionContext *execution_context) override;
132 
133     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
134       return llvm::ArrayRef(g_type_summary_add_options);
135     }
136 
137     // Instance variables to hold the values for command options.
138 
139     TypeSummaryImpl::Flags m_flags;
140     FormatterMatchType m_match_type = eFormatterMatchExact;
141     std::string m_format_string;
142     ConstString m_name;
143     std::string m_python_script;
144     std::string m_python_function;
145     bool m_is_add_script = false;
146     std::string m_category;
147   };
148 
149   CommandOptions m_options;
150 
151   Options *GetOptions() override { return &m_options; }
152 
153   bool Execute_ScriptSummary(Args &command, CommandReturnObject &result);
154 
155   bool Execute_StringSummary(Args &command, CommandReturnObject &result);
156 
157 public:
158   CommandObjectTypeSummaryAdd(CommandInterpreter &interpreter);
159 
160   ~CommandObjectTypeSummaryAdd() override = default;
161 
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 "
167         "for\n"
168         "        internal_dict: an LLDB support object not to be used\"\"\"\n";
169 
170     StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
171     if (output_sp && interactive) {
172       output_sp->PutCString(g_summary_addreader_instructions);
173       output_sp->Flush();
174     }
175   }
176 
177   void IOHandlerInputComplete(IOHandler &io_handler,
178                               std::string &data) override {
179     StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
180 
181 #if LLDB_ENABLE_PYTHON
182     ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
183     if (interpreter) {
184       StringList lines;
185       lines.SplitIntoLines(data);
186       if (lines.GetSize() > 0) {
187         ScriptAddOptions *options_ptr =
188             ((ScriptAddOptions *)io_handler.GetUserData());
189         if (options_ptr) {
190           ScriptAddOptions::SharedPointer options(
191               options_ptr); // this will ensure that we get rid of the pointer
192                             // when going out of scope
193 
194           ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
195           if (interpreter) {
196             std::string funct_name_str;
197             if (interpreter->GenerateTypeScriptFunction(lines,
198                                                         funct_name_str)) {
199               if (funct_name_str.empty()) {
200                 error_sp->Printf("unable to obtain a valid function name from "
201                                  "the script interpreter.\n");
202                 error_sp->Flush();
203               } else {
204                 // now I have a valid function name, let's add this as script
205                 // for every type in the list
206 
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());
211 
212                 Status error;
213 
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,
217                              &error);
218                   if (error.Fail()) {
219                     error_sp->Printf("error: %s", error.AsCString());
220                     error_sp->Flush();
221                   }
222                 }
223 
224                 if (options->m_name) {
225                   CommandObjectTypeSummaryAdd::AddNamedSummary(
226                       options->m_name, script_format, &error);
227                   if (error.Fail()) {
228                     CommandObjectTypeSummaryAdd::AddNamedSummary(
229                         options->m_name, script_format, &error);
230                     if (error.Fail()) {
231                       error_sp->Printf("error: %s", error.AsCString());
232                       error_sp->Flush();
233                     }
234                   } else {
235                     error_sp->Printf("error: %s", error.AsCString());
236                     error_sp->Flush();
237                   }
238                 } else {
239                   if (error.AsCString()) {
240                     error_sp->Printf("error: %s", error.AsCString());
241                     error_sp->Flush();
242                   }
243                 }
244               }
245             } else {
246               error_sp->Printf("error: unable to generate a function.\n");
247               error_sp->Flush();
248             }
249           } else {
250             error_sp->Printf("error: no script interpreter.\n");
251             error_sp->Flush();
252           }
253         } else {
254           error_sp->Printf("error: internal synchronization information "
255                            "missing or invalid.\n");
256           error_sp->Flush();
257         }
258       } else {
259         error_sp->Printf("error: empty function, didn't add python command.\n");
260         error_sp->Flush();
261       }
262     } else {
263       error_sp->Printf(
264           "error: script interpreter missing, didn't add python command.\n");
265       error_sp->Flush();
266     }
267 #endif
268     io_handler.SetIsDone(true);
269   }
270 
271   bool AddSummary(ConstString type_name, lldb::TypeSummaryImplSP entry,
272                   FormatterMatchType match_type, std::string category,
273                   Status *error = nullptr);
274 
275   bool AddNamedSummary(ConstString summary_name, lldb::TypeSummaryImplSP entry,
276                        Status *error = nullptr);
277 
278 protected:
279   bool DoExecute(Args &command, CommandReturnObject &result) override;
280 };
281 
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"
290     "        '''Optional'''\n"
291     "class synthProvider:\n";
292 
293 #define LLDB_OPTIONS_type_synth_add
294 #include "CommandOptions.inc"
295 
296 class CommandObjectTypeSynthAdd : public CommandObjectParsed,
297                                   public IOHandlerDelegateMultiline {
298 private:
299   class CommandOptions : public Options {
300   public:
301     CommandOptions() = default;
302 
303     ~CommandOptions() override = default;
304 
305     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
306                           ExecutionContext *execution_context) override {
307       Status error;
308       const int short_option = m_getopt_table[option_idx].val;
309       bool success;
310 
311       switch (short_option) {
312       case 'C':
313         m_cascade = OptionArgParser::ToBoolean(option_arg, true, &success);
314         if (!success)
315           error.SetErrorStringWithFormat("invalid value for cascade: %s",
316                                          option_arg.str().c_str());
317         break;
318       case 'P':
319         handwrite_python = true;
320         break;
321       case 'l':
322         m_class_name = std::string(option_arg);
323         is_class_based = true;
324         break;
325       case 'p':
326         m_skip_pointers = true;
327         break;
328       case 'r':
329         m_skip_references = true;
330         break;
331       case 'w':
332         m_category = std::string(option_arg);
333         break;
334       case 'x':
335         if (m_match_type == eFormatterMatchCallback)
336           error.SetErrorString(
337               "can't use --regex and --recognizer-function at the same time");
338         else
339           m_match_type = eFormatterMatchRegex;
340         break;
341       case '\x01':
342         if (m_match_type == eFormatterMatchRegex)
343           error.SetErrorString(
344               "can't use --regex and --recognizer-function at the same time");
345         else
346           m_match_type = eFormatterMatchCallback;
347         break;
348       default:
349         llvm_unreachable("Unimplemented option");
350       }
351 
352       return error;
353     }
354 
355     void OptionParsingStarting(ExecutionContext *execution_context) override {
356       m_cascade = true;
357       m_class_name = "";
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;
364     }
365 
366     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
367       return llvm::ArrayRef(g_type_synth_add_options);
368     }
369 
370     // Instance variables to hold the values for command options.
371 
372     bool m_cascade;
373     bool m_skip_references;
374     bool m_skip_pointers;
375     std::string m_class_name;
376     bool m_input_python;
377     std::string m_category;
378     bool is_class_based;
379     bool handwrite_python;
380     FormatterMatchType m_match_type;
381   };
382 
383   CommandOptions m_options;
384 
385   Options *GetOptions() override { return &m_options; }
386 
387   bool Execute_HandwritePython(Args &command, CommandReturnObject &result);
388 
389   bool Execute_PythonClass(Args &command, CommandReturnObject &result);
390 
391 protected:
392   bool DoExecute(Args &command, CommandReturnObject &result) override {
393     WarnOnPotentialUnquotedUnsignedType(command, result);
394 
395     if (m_options.handwrite_python)
396       return Execute_HandwritePython(command, result);
397     else if (m_options.is_class_based)
398       return Execute_PythonClass(command, result);
399     else {
400       result.AppendError("must either provide a children list, a Python class "
401                          "name, or use -P and type a Python class "
402                          "line-by-line");
403       return false;
404     }
405   }
406 
407   void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
408     StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
409     if (output_sp && interactive) {
410       output_sp->PutCString(g_synth_addreader_instructions);
411       output_sp->Flush();
412     }
413   }
414 
415   void IOHandlerInputComplete(IOHandler &io_handler,
416                               std::string &data) override {
417     StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
418 
419 #if LLDB_ENABLE_PYTHON
420     ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
421     if (interpreter) {
422       StringList lines;
423       lines.SplitIntoLines(data);
424       if (lines.GetSize() > 0) {
425         SynthAddOptions *options_ptr =
426             ((SynthAddOptions *)io_handler.GetUserData());
427         if (options_ptr) {
428           SynthAddOptions::SharedPointer options(
429               options_ptr); // this will ensure that we get rid of the pointer
430                             // when going out of scope
431 
432           ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
433           if (interpreter) {
434             std::string class_name_str;
435             if (interpreter->GenerateTypeSynthClass(lines, class_name_str)) {
436               if (class_name_str.empty()) {
437                 error_sp->Printf(
438                     "error: unable to obtain a proper name for the class.\n");
439                 error_sp->Flush();
440               } else {
441                 // everything should be fine now, let's add the synth provider
442                 // class
443 
444                 SyntheticChildrenSP synth_provider;
445                 synth_provider = std::make_shared<ScriptedSyntheticChildren>(
446                     SyntheticChildren::Flags()
447                         .SetCascades(options->m_cascade)
448                         .SetSkipPointers(options->m_skip_pointers)
449                         .SetSkipReferences(options->m_skip_references),
450                     class_name_str.c_str());
451 
452                 lldb::TypeCategoryImplSP category;
453                 DataVisualization::Categories::GetCategory(
454                     ConstString(options->m_category.c_str()), category);
455 
456                 Status error;
457 
458                 for (const std::string &type_name : options->m_target_types) {
459                   if (!type_name.empty()) {
460                     if (AddSynth(ConstString(type_name), synth_provider,
461                                  options->m_match_type, options->m_category,
462                                  &error)) {
463                       error_sp->Printf("error: %s\n", error.AsCString());
464                       error_sp->Flush();
465                       break;
466                     }
467                   } else {
468                     error_sp->Printf("error: invalid type name.\n");
469                     error_sp->Flush();
470                     break;
471                   }
472                 }
473               }
474             } else {
475               error_sp->Printf("error: unable to generate a class.\n");
476               error_sp->Flush();
477             }
478           } else {
479             error_sp->Printf("error: no script interpreter.\n");
480             error_sp->Flush();
481           }
482         } else {
483           error_sp->Printf("error: internal synchronization data missing.\n");
484           error_sp->Flush();
485         }
486       } else {
487         error_sp->Printf("error: empty function, didn't add python command.\n");
488         error_sp->Flush();
489       }
490     } else {
491       error_sp->Printf(
492           "error: script interpreter missing, didn't add python command.\n");
493       error_sp->Flush();
494     }
495 
496 #endif
497     io_handler.SetIsDone(true);
498   }
499 
500 public:
501   CommandObjectTypeSynthAdd(CommandInterpreter &interpreter);
502 
503   ~CommandObjectTypeSynthAdd() override = default;
504 
505   bool AddSynth(ConstString type_name, lldb::SyntheticChildrenSP entry,
506                 FormatterMatchType match_type, std::string category_name,
507                 Status *error);
508 };
509 
510 // CommandObjectTypeFormatAdd
511 
512 #define LLDB_OPTIONS_type_format_add
513 #include "CommandOptions.inc"
514 
515 class CommandObjectTypeFormatAdd : public CommandObjectParsed {
516 private:
517   class CommandOptions : public OptionGroup {
518   public:
519     CommandOptions() = default;
520 
521     ~CommandOptions() override = default;
522 
523     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
524       return llvm::ArrayRef(g_type_format_add_options);
525     }
526 
527     void OptionParsingStarting(ExecutionContext *execution_context) override {
528       m_cascade = true;
529       m_skip_pointers = false;
530       m_skip_references = false;
531       m_regex = false;
532       m_category.assign("default");
533       m_custom_type_name.clear();
534     }
535 
536     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
537                           ExecutionContext *execution_context) override {
538       Status error;
539       const int short_option =
540           g_type_format_add_options[option_idx].short_option;
541       bool success;
542 
543       switch (short_option) {
544       case 'C':
545         m_cascade = OptionArgParser::ToBoolean(option_value, true, &success);
546         if (!success)
547           error.SetErrorStringWithFormat("invalid value for cascade: %s",
548                                          option_value.str().c_str());
549         break;
550       case 'p':
551         m_skip_pointers = true;
552         break;
553       case 'w':
554         m_category.assign(std::string(option_value));
555         break;
556       case 'r':
557         m_skip_references = true;
558         break;
559       case 'x':
560         m_regex = true;
561         break;
562       case 't':
563         m_custom_type_name.assign(std::string(option_value));
564         break;
565       default:
566         llvm_unreachable("Unimplemented option");
567       }
568 
569       return error;
570     }
571 
572     // Instance variables to hold the values for command options.
573 
574     bool m_cascade;
575     bool m_skip_references;
576     bool m_skip_pointers;
577     bool m_regex;
578     std::string m_category;
579     std::string m_custom_type_name;
580   };
581 
582   OptionGroupOptions m_option_group;
583   OptionGroupFormat m_format_options;
584   CommandOptions m_command_options;
585 
586   Options *GetOptions() override { return &m_option_group; }
587 
588 public:
589   CommandObjectTypeFormatAdd(CommandInterpreter &interpreter)
590       : CommandObjectParsed(interpreter, "type format add",
591                             "Add a new formatting style for a type.", nullptr),
592         m_format_options(eFormatInvalid) {
593     CommandArgumentEntry type_arg;
594     CommandArgumentData type_style_arg;
595 
596     type_style_arg.arg_type = eArgTypeName;
597     type_style_arg.arg_repetition = eArgRepeatPlus;
598 
599     type_arg.push_back(type_style_arg);
600 
601     m_arguments.push_back(type_arg);
602 
603     SetHelpLong(
604         R"(
605 The following examples of 'type format add' refer to this code snippet for context:
606 
607     typedef int Aint;
608     typedef float Afloat;
609     typedef Aint Bint;
610     typedef Afloat Bfloat;
611 
612     Aint ix = 5;
613     Bint iy = 5;
614 
615     Afloat fx = 3.14;
616     BFloat fy = 3.14;
617 
618 Adding default formatting:
619 
620 (lldb) type format add -f hex AInt
621 (lldb) frame variable iy
622 
623 )"
624         "    Produces hexadecimal display of iy, because no formatter is available for Bint and \
625 the one for Aint is used instead."
626         R"(
627 
628 To prevent this use the cascade option '-C no' to prevent evaluation of typedef chains:
629 
630 
631 (lldb) type format add -f hex -C no AInt
632 
633 Similar reasoning applies to this:
634 
635 (lldb) type format add -f hex -C no float -p
636 
637 )"
638         "    All float values and float references are now formatted as hexadecimal, but not \
639 pointers to floats.  Nor will it change the default display for Afloat and Bfloat objects.");
640 
641     // Add the "--format" to all options groups
642     m_option_group.Append(&m_format_options,
643                           OptionGroupFormat::OPTION_GROUP_FORMAT,
644                           LLDB_OPT_SET_1);
645     m_option_group.Append(&m_command_options);
646     m_option_group.Finalize();
647   }
648 
649   ~CommandObjectTypeFormatAdd() override = default;
650 
651 protected:
652   bool DoExecute(Args &command, CommandReturnObject &result) override {
653     const size_t argc = command.GetArgumentCount();
654 
655     if (argc < 1) {
656       result.AppendErrorWithFormat("%s takes one or more args.\n",
657                                    m_cmd_name.c_str());
658       return false;
659     }
660 
661     const Format format = m_format_options.GetFormat();
662     if (format == eFormatInvalid &&
663         m_command_options.m_custom_type_name.empty()) {
664       result.AppendErrorWithFormat("%s needs a valid format.\n",
665                                    m_cmd_name.c_str());
666       return false;
667     }
668 
669     TypeFormatImplSP entry;
670 
671     if (m_command_options.m_custom_type_name.empty())
672       entry = std::make_shared<TypeFormatImpl_Format>(
673           format, TypeFormatImpl::Flags()
674                       .SetCascades(m_command_options.m_cascade)
675                       .SetSkipPointers(m_command_options.m_skip_pointers)
676                       .SetSkipReferences(m_command_options.m_skip_references));
677     else
678       entry = std::make_shared<TypeFormatImpl_EnumType>(
679           ConstString(m_command_options.m_custom_type_name.c_str()),
680           TypeFormatImpl::Flags()
681               .SetCascades(m_command_options.m_cascade)
682               .SetSkipPointers(m_command_options.m_skip_pointers)
683               .SetSkipReferences(m_command_options.m_skip_references));
684 
685     // now I have a valid format, let's add it to every type
686 
687     TypeCategoryImplSP category_sp;
688     DataVisualization::Categories::GetCategory(
689         ConstString(m_command_options.m_category), category_sp);
690     if (!category_sp)
691       return false;
692 
693     WarnOnPotentialUnquotedUnsignedType(command, result);
694 
695     for (auto &arg_entry : command.entries()) {
696       if (arg_entry.ref().empty()) {
697         result.AppendError("empty typenames not allowed");
698         return false;
699       }
700 
701       FormatterMatchType match_type = eFormatterMatchExact;
702       if (m_command_options.m_regex) {
703         match_type = eFormatterMatchRegex;
704         RegularExpression typeRX(arg_entry.ref());
705         if (!typeRX.IsValid()) {
706           result.AppendError(
707               "regex format error (maybe this is not really a regex?)");
708           return false;
709         }
710       }
711       category_sp->AddTypeFormat(arg_entry.ref(), match_type, entry);
712     }
713 
714     result.SetStatus(eReturnStatusSuccessFinishNoResult);
715     return result.Succeeded();
716   }
717 };
718 
719 #define LLDB_OPTIONS_type_formatter_delete
720 #include "CommandOptions.inc"
721 
722 class CommandObjectTypeFormatterDelete : public CommandObjectParsed {
723 protected:
724   class CommandOptions : public Options {
725   public:
726     CommandOptions() = default;
727 
728     ~CommandOptions() override = default;
729 
730     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
731                           ExecutionContext *execution_context) override {
732       Status error;
733       const int short_option = m_getopt_table[option_idx].val;
734 
735       switch (short_option) {
736       case 'a':
737         m_delete_all = true;
738         break;
739       case 'w':
740         m_category = std::string(option_arg);
741         break;
742       case 'l':
743         m_language = Language::GetLanguageTypeFromString(option_arg);
744         break;
745       default:
746         llvm_unreachable("Unimplemented option");
747       }
748 
749       return error;
750     }
751 
752     void OptionParsingStarting(ExecutionContext *execution_context) override {
753       m_delete_all = false;
754       m_category = "default";
755       m_language = lldb::eLanguageTypeUnknown;
756     }
757 
758     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
759       return llvm::ArrayRef(g_type_formatter_delete_options);
760     }
761 
762     // Instance variables to hold the values for command options.
763 
764     bool m_delete_all;
765     std::string m_category;
766     lldb::LanguageType m_language;
767   };
768 
769   CommandOptions m_options;
770   FormatCategoryItem m_formatter_kind;
771 
772   Options *GetOptions() override { return &m_options; }
773 
774   static constexpr const char *g_short_help_template =
775       "Delete an existing %s for a type.";
776 
777   static constexpr const char *g_long_help_template =
778       "Delete an existing %s for a type.  Unless you specify a "
779       "specific category or all categories, only the "
780       "'default' category is searched.  The names must be exactly as "
781       "shown in the 'type %s list' output";
782 
783 public:
784   CommandObjectTypeFormatterDelete(CommandInterpreter &interpreter,
785                                    FormatCategoryItem formatter_kind)
786       : CommandObjectParsed(interpreter,
787                             FormatCategoryToString(formatter_kind, false)),
788         m_formatter_kind(formatter_kind) {
789     CommandArgumentEntry type_arg;
790     CommandArgumentData type_style_arg;
791 
792     type_style_arg.arg_type = eArgTypeName;
793     type_style_arg.arg_repetition = eArgRepeatPlain;
794 
795     type_arg.push_back(type_style_arg);
796 
797     m_arguments.push_back(type_arg);
798 
799     const char *kind = FormatCategoryToString(formatter_kind, true);
800     const char *short_kind = FormatCategoryToString(formatter_kind, false);
801 
802     StreamString s;
803     s.Printf(g_short_help_template, kind);
804     SetHelp(s.GetData());
805     s.Clear();
806     s.Printf(g_long_help_template, kind, short_kind);
807     SetHelpLong(s.GetData());
808     s.Clear();
809     s.Printf("type %s delete", short_kind);
810     SetCommandName(s.GetData());
811   }
812 
813   ~CommandObjectTypeFormatterDelete() override = default;
814 
815   void
816   HandleArgumentCompletion(CompletionRequest &request,
817                            OptionElementVector &opt_element_vector) override {
818     if (request.GetCursorIndex())
819       return;
820 
821     DataVisualization::Categories::ForEach(
822         [this, &request](const lldb::TypeCategoryImplSP &category_sp) {
823           category_sp->AutoComplete(request, m_formatter_kind);
824           return true;
825         });
826   }
827 
828 protected:
829   virtual bool FormatterSpecificDeletion(ConstString typeCS) { return false; }
830 
831   bool DoExecute(Args &command, CommandReturnObject &result) override {
832     const size_t argc = command.GetArgumentCount();
833 
834     if (argc != 1) {
835       result.AppendErrorWithFormat("%s takes 1 arg.\n", m_cmd_name.c_str());
836       return false;
837     }
838 
839     const char *typeA = command.GetArgumentAtIndex(0);
840     ConstString typeCS(typeA);
841 
842     if (!typeCS) {
843       result.AppendError("empty typenames not allowed");
844       return false;
845     }
846 
847     if (m_options.m_delete_all) {
848       DataVisualization::Categories::ForEach(
849           [this, typeCS](const lldb::TypeCategoryImplSP &category_sp) -> bool {
850             category_sp->Delete(typeCS, m_formatter_kind);
851             return true;
852           });
853       result.SetStatus(eReturnStatusSuccessFinishNoResult);
854       return result.Succeeded();
855     }
856 
857     bool delete_category = false;
858     bool extra_deletion = false;
859 
860     if (m_options.m_language != lldb::eLanguageTypeUnknown) {
861       lldb::TypeCategoryImplSP category;
862       DataVisualization::Categories::GetCategory(m_options.m_language,
863                                                  category);
864       if (category)
865         delete_category = category->Delete(typeCS, m_formatter_kind);
866       extra_deletion = FormatterSpecificDeletion(typeCS);
867     } else {
868       lldb::TypeCategoryImplSP category;
869       DataVisualization::Categories::GetCategory(
870           ConstString(m_options.m_category.c_str()), category);
871       if (category)
872         delete_category = category->Delete(typeCS, m_formatter_kind);
873       extra_deletion = FormatterSpecificDeletion(typeCS);
874     }
875 
876     if (delete_category || extra_deletion) {
877       result.SetStatus(eReturnStatusSuccessFinishNoResult);
878       return result.Succeeded();
879     } else {
880       result.AppendErrorWithFormat("no custom formatter for %s.\n", typeA);
881       return false;
882     }
883   }
884 };
885 
886 #define LLDB_OPTIONS_type_formatter_clear
887 #include "CommandOptions.inc"
888 
889 class CommandObjectTypeFormatterClear : public CommandObjectParsed {
890 private:
891   class CommandOptions : public Options {
892   public:
893     CommandOptions() = default;
894 
895     ~CommandOptions() override = default;
896 
897     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
898                           ExecutionContext *execution_context) override {
899       Status error;
900       const int short_option = m_getopt_table[option_idx].val;
901 
902       switch (short_option) {
903       case 'a':
904         m_delete_all = true;
905         break;
906       default:
907         llvm_unreachable("Unimplemented option");
908       }
909 
910       return error;
911     }
912 
913     void OptionParsingStarting(ExecutionContext *execution_context) override {
914       m_delete_all = false;
915     }
916 
917     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
918       return llvm::ArrayRef(g_type_formatter_clear_options);
919     }
920 
921     // Instance variables to hold the values for command options.
922     bool m_delete_all;
923   };
924 
925   CommandOptions m_options;
926   FormatCategoryItem m_formatter_kind;
927 
928   Options *GetOptions() override { return &m_options; }
929 
930 public:
931   CommandObjectTypeFormatterClear(CommandInterpreter &interpreter,
932                                   FormatCategoryItem formatter_kind,
933                                   const char *name, const char *help)
934       : CommandObjectParsed(interpreter, name, help, nullptr),
935         m_formatter_kind(formatter_kind) {
936     CommandArgumentData category_arg{eArgTypeName, eArgRepeatOptional};
937     m_arguments.push_back({category_arg});
938   }
939 
940   ~CommandObjectTypeFormatterClear() override = default;
941 
942 protected:
943   virtual void FormatterSpecificDeletion() {}
944 
945   bool DoExecute(Args &command, CommandReturnObject &result) override {
946     if (m_options.m_delete_all) {
947       DataVisualization::Categories::ForEach(
948           [this](const TypeCategoryImplSP &category_sp) -> bool {
949             category_sp->Clear(m_formatter_kind);
950             return true;
951           });
952     } else {
953       lldb::TypeCategoryImplSP category;
954       if (command.GetArgumentCount() > 0) {
955         const char *cat_name = command.GetArgumentAtIndex(0);
956         ConstString cat_nameCS(cat_name);
957         DataVisualization::Categories::GetCategory(cat_nameCS, category);
958       } else {
959         DataVisualization::Categories::GetCategory(ConstString(nullptr),
960                                                    category);
961       }
962       category->Clear(m_formatter_kind);
963     }
964 
965     FormatterSpecificDeletion();
966 
967     result.SetStatus(eReturnStatusSuccessFinishResult);
968     return result.Succeeded();
969   }
970 };
971 
972 // CommandObjectTypeFormatDelete
973 
974 class CommandObjectTypeFormatDelete : public CommandObjectTypeFormatterDelete {
975 public:
976   CommandObjectTypeFormatDelete(CommandInterpreter &interpreter)
977       : CommandObjectTypeFormatterDelete(
978             interpreter, eFormatCategoryItemFormat) {}
979 
980   ~CommandObjectTypeFormatDelete() override = default;
981 };
982 
983 // CommandObjectTypeFormatClear
984 
985 class CommandObjectTypeFormatClear : public CommandObjectTypeFormatterClear {
986 public:
987   CommandObjectTypeFormatClear(CommandInterpreter &interpreter)
988       : CommandObjectTypeFormatterClear(interpreter, eFormatCategoryItemFormat,
989                                         "type format clear",
990                                         "Delete all existing format styles.") {}
991 };
992 
993 #define LLDB_OPTIONS_type_formatter_list
994 #include "CommandOptions.inc"
995 
996 template <typename FormatterType>
997 class CommandObjectTypeFormatterList : public CommandObjectParsed {
998   typedef typename FormatterType::SharedPointer FormatterSharedPointer;
999 
1000   class CommandOptions : public Options {
1001   public:
1002     CommandOptions()
1003         : Options(), m_category_regex("", ""),
1004           m_category_language(lldb::eLanguageTypeUnknown,
1005                               lldb::eLanguageTypeUnknown) {}
1006 
1007     ~CommandOptions() override = default;
1008 
1009     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1010                           ExecutionContext *execution_context) override {
1011       Status error;
1012       const int short_option = m_getopt_table[option_idx].val;
1013       switch (short_option) {
1014       case 'w':
1015         m_category_regex.SetCurrentValue(option_arg);
1016         m_category_regex.SetOptionWasSet();
1017         break;
1018       case 'l':
1019         error = m_category_language.SetValueFromString(option_arg);
1020         if (error.Success())
1021           m_category_language.SetOptionWasSet();
1022         break;
1023       default:
1024         llvm_unreachable("Unimplemented option");
1025       }
1026 
1027       return error;
1028     }
1029 
1030     void OptionParsingStarting(ExecutionContext *execution_context) override {
1031       m_category_regex.Clear();
1032       m_category_language.Clear();
1033     }
1034 
1035     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1036       return llvm::ArrayRef(g_type_formatter_list_options);
1037     }
1038 
1039     // Instance variables to hold the values for command options.
1040 
1041     OptionValueString m_category_regex;
1042     OptionValueLanguage m_category_language;
1043   };
1044 
1045   CommandOptions m_options;
1046 
1047   Options *GetOptions() override { return &m_options; }
1048 
1049 public:
1050   CommandObjectTypeFormatterList(CommandInterpreter &interpreter,
1051                                  const char *name, const char *help)
1052       : CommandObjectParsed(interpreter, name, help, nullptr), m_options() {
1053     CommandArgumentEntry type_arg;
1054     CommandArgumentData type_style_arg;
1055 
1056     type_style_arg.arg_type = eArgTypeName;
1057     type_style_arg.arg_repetition = eArgRepeatOptional;
1058 
1059     type_arg.push_back(type_style_arg);
1060 
1061     m_arguments.push_back(type_arg);
1062   }
1063 
1064   ~CommandObjectTypeFormatterList() override = default;
1065 
1066 protected:
1067   virtual bool FormatterSpecificList(CommandReturnObject &result) {
1068     return false;
1069   }
1070 
1071   static bool ShouldListItem(llvm::StringRef s, RegularExpression *regex) {
1072     // If we have a regex, it can match two kinds of results:
1073     //   - An item created with that same regex string (exact string match), so
1074     //     the user can list it using the same string it used at creation time.
1075     //   - Items that match the regex.
1076     // No regex means list everything.
1077     return regex == nullptr || s == regex->GetText() || regex->Execute(s);
1078   }
1079 
1080   bool DoExecute(Args &command, CommandReturnObject &result) override {
1081     const size_t argc = command.GetArgumentCount();
1082 
1083     std::unique_ptr<RegularExpression> category_regex;
1084     std::unique_ptr<RegularExpression> formatter_regex;
1085 
1086     if (m_options.m_category_regex.OptionWasSet()) {
1087       category_regex = std::make_unique<RegularExpression>(
1088           m_options.m_category_regex.GetCurrentValueAsRef());
1089       if (!category_regex->IsValid()) {
1090         result.AppendErrorWithFormat(
1091             "syntax error in category regular expression '%s'",
1092             m_options.m_category_regex.GetCurrentValueAsRef().str().c_str());
1093         return false;
1094       }
1095     }
1096 
1097     if (argc == 1) {
1098       const char *arg = command.GetArgumentAtIndex(0);
1099       formatter_regex = std::make_unique<RegularExpression>(arg);
1100       if (!formatter_regex->IsValid()) {
1101         result.AppendErrorWithFormat("syntax error in regular expression '%s'",
1102                                      arg);
1103         return false;
1104       }
1105     }
1106 
1107     bool any_printed = false;
1108 
1109     auto category_closure =
1110         [&result, &formatter_regex,
1111          &any_printed](const lldb::TypeCategoryImplSP &category) -> void {
1112       result.GetOutputStream().Printf(
1113           "-----------------------\nCategory: %s%s\n-----------------------\n",
1114           category->GetName(), category->IsEnabled() ? "" : " (disabled)");
1115 
1116       TypeCategoryImpl::ForEachCallback<FormatterType> print_formatter =
1117           [&result, &formatter_regex,
1118            &any_printed](const TypeMatcher &type_matcher,
1119                          const FormatterSharedPointer &format_sp) -> bool {
1120         if (ShouldListItem(type_matcher.GetMatchString().GetStringRef(),
1121                            formatter_regex.get())) {
1122           any_printed = true;
1123           result.GetOutputStream().Printf(
1124               "%s: %s\n", type_matcher.GetMatchString().GetCString(),
1125               format_sp->GetDescription().c_str());
1126         }
1127         return true;
1128       };
1129       category->ForEach(print_formatter);
1130     };
1131 
1132     if (m_options.m_category_language.OptionWasSet()) {
1133       lldb::TypeCategoryImplSP category_sp;
1134       DataVisualization::Categories::GetCategory(
1135           m_options.m_category_language.GetCurrentValue(), category_sp);
1136       if (category_sp)
1137         category_closure(category_sp);
1138     } else {
1139       DataVisualization::Categories::ForEach(
1140           [&category_regex, &category_closure](
1141               const lldb::TypeCategoryImplSP &category) -> bool {
1142             if (ShouldListItem(category->GetName(), category_regex.get())) {
1143               category_closure(category);
1144             }
1145             return true;
1146           });
1147 
1148       any_printed = FormatterSpecificList(result) | any_printed;
1149     }
1150 
1151     if (any_printed)
1152       result.SetStatus(eReturnStatusSuccessFinishResult);
1153     else {
1154       result.GetOutputStream().PutCString("no matching results found.\n");
1155       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1156     }
1157     return result.Succeeded();
1158   }
1159 };
1160 
1161 // CommandObjectTypeFormatList
1162 
1163 class CommandObjectTypeFormatList
1164     : public CommandObjectTypeFormatterList<TypeFormatImpl> {
1165 public:
1166   CommandObjectTypeFormatList(CommandInterpreter &interpreter)
1167       : CommandObjectTypeFormatterList(interpreter, "type format list",
1168                                        "Show a list of current formats.") {}
1169 };
1170 
1171 Status CommandObjectTypeSummaryAdd::CommandOptions::SetOptionValue(
1172     uint32_t option_idx, llvm::StringRef option_arg,
1173     ExecutionContext *execution_context) {
1174   Status error;
1175   const int short_option = m_getopt_table[option_idx].val;
1176   bool success;
1177 
1178   switch (short_option) {
1179   case 'C':
1180     m_flags.SetCascades(OptionArgParser::ToBoolean(option_arg, true, &success));
1181     if (!success)
1182       error.SetErrorStringWithFormat("invalid value for cascade: %s",
1183                                      option_arg.str().c_str());
1184     break;
1185   case 'e':
1186     m_flags.SetDontShowChildren(false);
1187     break;
1188   case 'h':
1189     m_flags.SetHideEmptyAggregates(true);
1190     break;
1191   case 'v':
1192     m_flags.SetDontShowValue(true);
1193     break;
1194   case 'c':
1195     m_flags.SetShowMembersOneLiner(true);
1196     break;
1197   case 's':
1198     m_format_string = std::string(option_arg);
1199     break;
1200   case 'p':
1201     m_flags.SetSkipPointers(true);
1202     break;
1203   case 'r':
1204     m_flags.SetSkipReferences(true);
1205     break;
1206   case 'x':
1207     if (m_match_type == eFormatterMatchCallback)
1208       error.SetErrorString(
1209           "can't use --regex and --recognizer-function at the same time");
1210     else
1211       m_match_type = eFormatterMatchRegex;
1212     break;
1213   case '\x01':
1214     if (m_match_type == eFormatterMatchRegex)
1215       error.SetErrorString(
1216           "can't use --regex and --recognizer-function at the same time");
1217     else
1218       m_match_type = eFormatterMatchCallback;
1219     break;
1220   case 'n':
1221     m_name.SetString(option_arg);
1222     break;
1223   case 'o':
1224     m_python_script = std::string(option_arg);
1225     m_is_add_script = true;
1226     break;
1227   case 'F':
1228     m_python_function = std::string(option_arg);
1229     m_is_add_script = true;
1230     break;
1231   case 'P':
1232     m_is_add_script = true;
1233     break;
1234   case 'w':
1235     m_category = std::string(option_arg);
1236     break;
1237   case 'O':
1238     m_flags.SetHideItemNames(true);
1239     break;
1240   default:
1241     llvm_unreachable("Unimplemented option");
1242   }
1243 
1244   return error;
1245 }
1246 
1247 void CommandObjectTypeSummaryAdd::CommandOptions::OptionParsingStarting(
1248     ExecutionContext *execution_context) {
1249   m_flags.Clear().SetCascades().SetDontShowChildren().SetDontShowValue(false);
1250   m_flags.SetShowMembersOneLiner(false)
1251       .SetSkipPointers(false)
1252       .SetSkipReferences(false)
1253       .SetHideItemNames(false);
1254 
1255   m_match_type = eFormatterMatchExact;
1256   m_name.Clear();
1257   m_python_script = "";
1258   m_python_function = "";
1259   m_format_string = "";
1260   m_is_add_script = false;
1261   m_category = "default";
1262 }
1263 
1264 #if LLDB_ENABLE_PYTHON
1265 
1266 bool CommandObjectTypeSummaryAdd::Execute_ScriptSummary(
1267     Args &command, CommandReturnObject &result) {
1268   const size_t argc = command.GetArgumentCount();
1269 
1270   if (argc < 1 && !m_options.m_name) {
1271     result.AppendErrorWithFormat("%s takes one or more args.\n",
1272                                  m_cmd_name.c_str());
1273     return false;
1274   }
1275 
1276   TypeSummaryImplSP script_format;
1277 
1278   if (!m_options.m_python_function
1279            .empty()) // we have a Python function ready to use
1280   {
1281     const char *funct_name = m_options.m_python_function.c_str();
1282     if (!funct_name || !funct_name[0]) {
1283       result.AppendError("function name empty.\n");
1284       return false;
1285     }
1286 
1287     std::string code =
1288         ("    " + m_options.m_python_function + "(valobj,internal_dict)");
1289 
1290     script_format = std::make_shared<ScriptSummaryFormat>(
1291         m_options.m_flags, funct_name, code.c_str());
1292 
1293     ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
1294 
1295     if (interpreter && !interpreter->CheckObjectExists(funct_name))
1296       result.AppendWarningWithFormat(
1297           "The provided function \"%s\" does not exist - "
1298           "please define it before attempting to use this summary.\n",
1299           funct_name);
1300   } else if (!m_options.m_python_script
1301                   .empty()) // we have a quick 1-line script, just use it
1302   {
1303     ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
1304     if (!interpreter) {
1305       result.AppendError("script interpreter missing - unable to generate "
1306                          "function wrapper.\n");
1307       return false;
1308     }
1309     StringList funct_sl;
1310     funct_sl << m_options.m_python_script.c_str();
1311     std::string funct_name_str;
1312     if (!interpreter->GenerateTypeScriptFunction(funct_sl, funct_name_str)) {
1313       result.AppendError("unable to generate function wrapper.\n");
1314       return false;
1315     }
1316     if (funct_name_str.empty()) {
1317       result.AppendError(
1318           "script interpreter failed to generate a valid function name.\n");
1319       return false;
1320     }
1321 
1322     std::string code = "    " + m_options.m_python_script;
1323 
1324     script_format = std::make_shared<ScriptSummaryFormat>(
1325         m_options.m_flags, funct_name_str.c_str(), code.c_str());
1326   } else {
1327     // Use an IOHandler to grab Python code from the user
1328     auto options = std::make_unique<ScriptAddOptions>(
1329         m_options.m_flags, m_options.m_match_type, m_options.m_name,
1330         m_options.m_category);
1331 
1332     for (auto &entry : command.entries()) {
1333       if (entry.ref().empty()) {
1334         result.AppendError("empty typenames not allowed");
1335         return false;
1336       }
1337 
1338       options->m_target_types << std::string(entry.ref());
1339     }
1340 
1341     m_interpreter.GetPythonCommandsFromIOHandler(
1342         "    ",             // Prompt
1343         *this,              // IOHandlerDelegate
1344         options.release()); // Baton for the "io_handler" that will be passed
1345                             // back into our IOHandlerDelegate functions
1346     result.SetStatus(eReturnStatusSuccessFinishNoResult);
1347 
1348     return result.Succeeded();
1349   }
1350 
1351   // if I am here, script_format must point to something good, so I can add
1352   // that as a script summary to all interested parties
1353 
1354   Status error;
1355 
1356   for (auto &entry : command.entries()) {
1357     AddSummary(ConstString(entry.ref()), script_format, m_options.m_match_type,
1358                m_options.m_category, &error);
1359     if (error.Fail()) {
1360       result.AppendError(error.AsCString());
1361       return false;
1362     }
1363   }
1364 
1365   if (m_options.m_name) {
1366     AddNamedSummary(m_options.m_name, script_format, &error);
1367     if (error.Fail()) {
1368       result.AppendError(error.AsCString());
1369       result.AppendError("added to types, but not given a name");
1370       return false;
1371     }
1372   }
1373 
1374   return result.Succeeded();
1375 }
1376 
1377 #endif
1378 
1379 bool CommandObjectTypeSummaryAdd::Execute_StringSummary(
1380     Args &command, CommandReturnObject &result) {
1381   const size_t argc = command.GetArgumentCount();
1382 
1383   if (argc < 1 && !m_options.m_name) {
1384     result.AppendErrorWithFormat("%s takes one or more args.\n",
1385                                  m_cmd_name.c_str());
1386     return false;
1387   }
1388 
1389   if (!m_options.m_flags.GetShowMembersOneLiner() &&
1390       m_options.m_format_string.empty()) {
1391     result.AppendError("empty summary strings not allowed");
1392     return false;
1393   }
1394 
1395   const char *format_cstr = (m_options.m_flags.GetShowMembersOneLiner()
1396                                  ? ""
1397                                  : m_options.m_format_string.c_str());
1398 
1399   // ${var%S} is an endless recursion, prevent it
1400   if (strcmp(format_cstr, "${var%S}") == 0) {
1401     result.AppendError("recursive summary not allowed");
1402     return false;
1403   }
1404 
1405   std::unique_ptr<StringSummaryFormat> string_format(
1406       new StringSummaryFormat(m_options.m_flags, format_cstr));
1407   if (!string_format) {
1408     result.AppendError("summary creation failed");
1409     return false;
1410   }
1411   if (string_format->m_error.Fail()) {
1412     result.AppendErrorWithFormat("syntax error: %s",
1413                                  string_format->m_error.AsCString("<unknown>"));
1414     return false;
1415   }
1416   lldb::TypeSummaryImplSP entry(string_format.release());
1417 
1418   // now I have a valid format, let's add it to every type
1419   Status error;
1420   for (auto &arg_entry : command.entries()) {
1421     if (arg_entry.ref().empty()) {
1422       result.AppendError("empty typenames not allowed");
1423       return false;
1424     }
1425     ConstString typeCS(arg_entry.ref());
1426 
1427     AddSummary(typeCS, entry, m_options.m_match_type, m_options.m_category,
1428                &error);
1429 
1430     if (error.Fail()) {
1431       result.AppendError(error.AsCString());
1432       return false;
1433     }
1434   }
1435 
1436   if (m_options.m_name) {
1437     AddNamedSummary(m_options.m_name, entry, &error);
1438     if (error.Fail()) {
1439       result.AppendError(error.AsCString());
1440       result.AppendError("added to types, but not given a name");
1441       return false;
1442     }
1443   }
1444 
1445   result.SetStatus(eReturnStatusSuccessFinishNoResult);
1446   return result.Succeeded();
1447 }
1448 
1449 CommandObjectTypeSummaryAdd::CommandObjectTypeSummaryAdd(
1450     CommandInterpreter &interpreter)
1451     : CommandObjectParsed(interpreter, "type summary add",
1452                           "Add a new summary style for a type.", nullptr),
1453       IOHandlerDelegateMultiline("DONE"), m_options(interpreter) {
1454   CommandArgumentEntry type_arg;
1455   CommandArgumentData type_style_arg;
1456 
1457   type_style_arg.arg_type = eArgTypeName;
1458   type_style_arg.arg_repetition = eArgRepeatPlus;
1459 
1460   type_arg.push_back(type_style_arg);
1461 
1462   m_arguments.push_back(type_arg);
1463 
1464   SetHelpLong(
1465       R"(
1466 The following examples of 'type summary add' refer to this code snippet for context:
1467 
1468     struct JustADemo
1469     {
1470         int* ptr;
1471         float value;
1472         JustADemo(int p = 1, float v = 0.1) : ptr(new int(p)), value(v) {}
1473     };
1474     JustADemo demo_instance(42, 3.14);
1475 
1476     typedef JustADemo NewDemo;
1477     NewDemo new_demo_instance(42, 3.14);
1478 
1479 (lldb) type summary add --summary-string "the answer is ${*var.ptr}" JustADemo
1480 
1481     Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42"
1482 
1483 (lldb) type summary add --summary-string "the answer is ${*var.ptr}, and the question is ${var.value}" JustADemo
1484 
1485     Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42 and the question is 3.14"
1486 
1487 )"
1488       "Alternatively, you could define formatting for all pointers to integers and \
1489 rely on that when formatting JustADemo to obtain the same result:"
1490       R"(
1491 
1492 (lldb) type summary add --summary-string "${var%V} -> ${*var}" "int *"
1493 (lldb) type summary add --summary-string "the answer is ${var.ptr}, and the question is ${var.value}" JustADemo
1494 
1495 )"
1496       "Type summaries are automatically applied to derived typedefs, so the examples \
1497 above apply to both JustADemo and NewDemo.  The cascade option can be used to \
1498 suppress this behavior:"
1499       R"(
1500 
1501 (lldb) type summary add --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo -C no
1502 
1503     The summary will now be used for values of JustADemo but not NewDemo.
1504 
1505 )"
1506       "By default summaries are shown for pointers and references to values of the \
1507 specified type.  To suppress formatting for pointers use the -p option, or apply \
1508 the corresponding -r option to suppress formatting for references:"
1509       R"(
1510 
1511 (lldb) type summary add -p -r --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo
1512 
1513 )"
1514       "One-line summaries including all fields in a type can be inferred without supplying an \
1515 explicit summary string by passing the -c option:"
1516       R"(
1517 
1518 (lldb) type summary add -c JustADemo
1519 (lldb) frame variable demo_instance
1520 (ptr=<address>, value=3.14)
1521 
1522 )"
1523       "Type summaries normally suppress the nested display of individual fields.  To \
1524 supply a summary to supplement the default structure add the -e option:"
1525       R"(
1526 
1527 (lldb) type summary add -e --summary-string "*ptr = ${*var.ptr}" JustADemo
1528 
1529 )"
1530       "Now when displaying JustADemo values the int* is displayed, followed by the \
1531 standard LLDB sequence of children, one per line:"
1532       R"(
1533 
1534 *ptr = 42 {
1535   ptr = <address>
1536   value = 3.14
1537 }
1538 
1539 )"
1540       "You can also add summaries written in Python.  These scripts use lldb public API to \
1541 gather information from your variables and produce a meaningful summary.  To start a \
1542 multi-line script use the -P option.  The function declaration will be displayed along with \
1543 a comment describing the two arguments.  End your script with the  word 'DONE' on a line by \
1544 itself:"
1545       R"(
1546 
1547 (lldb) type summary add JustADemo -P
1548 def function (valobj,internal_dict):
1549 """valobj: an SBValue which you want to provide a summary for
1550 internal_dict: an LLDB support object not to be used"""
1551     value = valobj.GetChildMemberWithName('value');
1552     return 'My value is ' + value.GetValue();
1553     DONE
1554 
1555 Alternatively, the -o option can be used when providing a simple one-line Python script:
1556 
1557 (lldb) type summary add JustADemo -o "value = valobj.GetChildMemberWithName('value'); return 'My value is ' + value.GetValue();")");
1558 }
1559 
1560 bool CommandObjectTypeSummaryAdd::DoExecute(Args &command,
1561                                             CommandReturnObject &result) {
1562   WarnOnPotentialUnquotedUnsignedType(command, result);
1563 
1564   if (m_options.m_is_add_script) {
1565 #if LLDB_ENABLE_PYTHON
1566     return Execute_ScriptSummary(command, result);
1567 #else
1568     result.AppendError("python is disabled");
1569     return false;
1570 #endif
1571   }
1572 
1573   return Execute_StringSummary(command, result);
1574 }
1575 
1576 static bool FixArrayTypeNameWithRegex(ConstString &type_name) {
1577   llvm::StringRef type_name_ref(type_name.GetStringRef());
1578 
1579   if (type_name_ref.endswith("[]")) {
1580     std::string type_name_str(type_name.GetCString());
1581     type_name_str.resize(type_name_str.length() - 2);
1582     if (type_name_str.back() != ' ')
1583       type_name_str.append(" ?\\[[0-9]+\\]");
1584     else
1585       type_name_str.append("\\[[0-9]+\\]");
1586     type_name.SetCString(type_name_str.c_str());
1587     return true;
1588   }
1589   return false;
1590 }
1591 
1592 bool CommandObjectTypeSummaryAdd::AddNamedSummary(ConstString summary_name,
1593                                                   TypeSummaryImplSP entry,
1594                                                   Status *error) {
1595   // system named summaries do not exist (yet?)
1596   DataVisualization::NamedSummaryFormats::Add(summary_name, entry);
1597   return true;
1598 }
1599 
1600 bool CommandObjectTypeSummaryAdd::AddSummary(ConstString type_name,
1601                                              TypeSummaryImplSP entry,
1602                                              FormatterMatchType match_type,
1603                                              std::string category_name,
1604                                              Status *error) {
1605   lldb::TypeCategoryImplSP category;
1606   DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()),
1607                                              category);
1608 
1609   if (match_type == eFormatterMatchExact) {
1610     if (FixArrayTypeNameWithRegex(type_name))
1611       match_type = eFormatterMatchRegex;
1612   }
1613 
1614   if (match_type == eFormatterMatchRegex) {
1615     match_type = eFormatterMatchRegex;
1616     RegularExpression typeRX(type_name.GetStringRef());
1617     if (!typeRX.IsValid()) {
1618       if (error)
1619         error->SetErrorString(
1620             "regex format error (maybe this is not really a regex?)");
1621       return false;
1622     }
1623   }
1624 
1625   if (match_type == eFormatterMatchCallback) {
1626     const char *function_name = type_name.AsCString();
1627     ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
1628     if (interpreter && !interpreter->CheckObjectExists(function_name)) {
1629       error->SetErrorStringWithFormat(
1630           "The provided recognizer function \"%s\" does not exist - "
1631           "please define it before attempting to use this summary.\n",
1632           function_name);
1633       return false;
1634     }
1635   }
1636   category->AddTypeSummary(type_name.GetStringRef(), match_type, entry);
1637   return true;
1638 }
1639 
1640 // CommandObjectTypeSummaryDelete
1641 
1642 class CommandObjectTypeSummaryDelete : public CommandObjectTypeFormatterDelete {
1643 public:
1644   CommandObjectTypeSummaryDelete(CommandInterpreter &interpreter)
1645       : CommandObjectTypeFormatterDelete(
1646             interpreter, eFormatCategoryItemSummary) {}
1647 
1648   ~CommandObjectTypeSummaryDelete() override = default;
1649 
1650 protected:
1651   bool FormatterSpecificDeletion(ConstString typeCS) override {
1652     if (m_options.m_language != lldb::eLanguageTypeUnknown)
1653       return false;
1654     return DataVisualization::NamedSummaryFormats::Delete(typeCS);
1655   }
1656 };
1657 
1658 class CommandObjectTypeSummaryClear : public CommandObjectTypeFormatterClear {
1659 public:
1660   CommandObjectTypeSummaryClear(CommandInterpreter &interpreter)
1661       : CommandObjectTypeFormatterClear(interpreter, eFormatCategoryItemSummary,
1662                                         "type summary clear",
1663                                         "Delete all existing summaries.") {}
1664 
1665 protected:
1666   void FormatterSpecificDeletion() override {
1667     DataVisualization::NamedSummaryFormats::Clear();
1668   }
1669 };
1670 
1671 // CommandObjectTypeSummaryList
1672 
1673 class CommandObjectTypeSummaryList
1674     : public CommandObjectTypeFormatterList<TypeSummaryImpl> {
1675 public:
1676   CommandObjectTypeSummaryList(CommandInterpreter &interpreter)
1677       : CommandObjectTypeFormatterList(interpreter, "type summary list",
1678                                        "Show a list of current summaries.") {}
1679 
1680 protected:
1681   bool FormatterSpecificList(CommandReturnObject &result) override {
1682     if (DataVisualization::NamedSummaryFormats::GetCount() > 0) {
1683       result.GetOutputStream().Printf("Named summaries:\n");
1684       DataVisualization::NamedSummaryFormats::ForEach(
1685           [&result](const TypeMatcher &type_matcher,
1686                     const TypeSummaryImplSP &summary_sp) -> bool {
1687             result.GetOutputStream().Printf(
1688                 "%s: %s\n", type_matcher.GetMatchString().GetCString(),
1689                 summary_sp->GetDescription().c_str());
1690             return true;
1691           });
1692       return true;
1693     }
1694     return false;
1695   }
1696 };
1697 
1698 // CommandObjectTypeCategoryDefine
1699 #define LLDB_OPTIONS_type_category_define
1700 #include "CommandOptions.inc"
1701 
1702 class CommandObjectTypeCategoryDefine : public CommandObjectParsed {
1703   class CommandOptions : public Options {
1704   public:
1705     CommandOptions()
1706         : m_define_enabled(false, false),
1707           m_cate_language(eLanguageTypeUnknown, eLanguageTypeUnknown) {}
1708 
1709     ~CommandOptions() override = default;
1710 
1711     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1712                           ExecutionContext *execution_context) override {
1713       Status error;
1714       const int short_option = m_getopt_table[option_idx].val;
1715 
1716       switch (short_option) {
1717       case 'e':
1718         m_define_enabled.SetValueFromString(llvm::StringRef("true"));
1719         break;
1720       case 'l':
1721         error = m_cate_language.SetValueFromString(option_arg);
1722         break;
1723       default:
1724         llvm_unreachable("Unimplemented option");
1725       }
1726 
1727       return error;
1728     }
1729 
1730     void OptionParsingStarting(ExecutionContext *execution_context) override {
1731       m_define_enabled.Clear();
1732       m_cate_language.Clear();
1733     }
1734 
1735     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1736       return llvm::ArrayRef(g_type_category_define_options);
1737     }
1738 
1739     // Instance variables to hold the values for command options.
1740 
1741     OptionValueBoolean m_define_enabled;
1742     OptionValueLanguage m_cate_language;
1743   };
1744 
1745   CommandOptions m_options;
1746 
1747   Options *GetOptions() override { return &m_options; }
1748 
1749 public:
1750   CommandObjectTypeCategoryDefine(CommandInterpreter &interpreter)
1751       : CommandObjectParsed(interpreter, "type category define",
1752                             "Define a new category as a source of formatters.",
1753                             nullptr) {
1754     CommandArgumentEntry type_arg;
1755     CommandArgumentData type_style_arg;
1756 
1757     type_style_arg.arg_type = eArgTypeName;
1758     type_style_arg.arg_repetition = eArgRepeatPlus;
1759 
1760     type_arg.push_back(type_style_arg);
1761 
1762     m_arguments.push_back(type_arg);
1763   }
1764 
1765   ~CommandObjectTypeCategoryDefine() override = default;
1766 
1767   void
1768   HandleArgumentCompletion(CompletionRequest &request,
1769                            OptionElementVector &opt_element_vector) override {
1770     lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1771         GetCommandInterpreter(), lldb::eTypeCategoryNameCompletion, request,
1772         nullptr);
1773   }
1774 
1775 protected:
1776   bool DoExecute(Args &command, CommandReturnObject &result) override {
1777     const size_t argc = command.GetArgumentCount();
1778 
1779     if (argc < 1) {
1780       result.AppendErrorWithFormat("%s takes 1 or more args.\n",
1781                                    m_cmd_name.c_str());
1782       return false;
1783     }
1784 
1785     for (auto &entry : command.entries()) {
1786       TypeCategoryImplSP category_sp;
1787       if (DataVisualization::Categories::GetCategory(ConstString(entry.ref()),
1788                                                      category_sp) &&
1789           category_sp) {
1790         category_sp->AddLanguage(m_options.m_cate_language.GetCurrentValue());
1791         if (m_options.m_define_enabled.GetCurrentValue())
1792           DataVisualization::Categories::Enable(category_sp,
1793                                                 TypeCategoryMap::Default);
1794       }
1795     }
1796 
1797     result.SetStatus(eReturnStatusSuccessFinishResult);
1798     return result.Succeeded();
1799   }
1800 };
1801 
1802 // CommandObjectTypeCategoryEnable
1803 #define LLDB_OPTIONS_type_category_enable
1804 #include "CommandOptions.inc"
1805 
1806 class CommandObjectTypeCategoryEnable : public CommandObjectParsed {
1807   class CommandOptions : public Options {
1808   public:
1809     CommandOptions() = default;
1810 
1811     ~CommandOptions() override = default;
1812 
1813     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1814                           ExecutionContext *execution_context) override {
1815       Status error;
1816       const int short_option = m_getopt_table[option_idx].val;
1817 
1818       switch (short_option) {
1819       case 'l':
1820         if (!option_arg.empty()) {
1821           m_language = Language::GetLanguageTypeFromString(option_arg);
1822           if (m_language == lldb::eLanguageTypeUnknown)
1823             error.SetErrorStringWithFormat("unrecognized language '%s'",
1824                                            option_arg.str().c_str());
1825         }
1826         break;
1827       default:
1828         llvm_unreachable("Unimplemented option");
1829       }
1830 
1831       return error;
1832     }
1833 
1834     void OptionParsingStarting(ExecutionContext *execution_context) override {
1835       m_language = lldb::eLanguageTypeUnknown;
1836     }
1837 
1838     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1839       return llvm::ArrayRef(g_type_category_enable_options);
1840     }
1841 
1842     // Instance variables to hold the values for command options.
1843 
1844     lldb::LanguageType m_language;
1845   };
1846 
1847   CommandOptions m_options;
1848 
1849   Options *GetOptions() override { return &m_options; }
1850 
1851 public:
1852   CommandObjectTypeCategoryEnable(CommandInterpreter &interpreter)
1853       : CommandObjectParsed(interpreter, "type category enable",
1854                             "Enable a category as a source of formatters.",
1855                             nullptr) {
1856     CommandArgumentEntry type_arg;
1857     CommandArgumentData type_style_arg;
1858 
1859     type_style_arg.arg_type = eArgTypeName;
1860     type_style_arg.arg_repetition = eArgRepeatPlus;
1861 
1862     type_arg.push_back(type_style_arg);
1863 
1864     m_arguments.push_back(type_arg);
1865   }
1866 
1867   ~CommandObjectTypeCategoryEnable() override = default;
1868 
1869   void
1870   HandleArgumentCompletion(CompletionRequest &request,
1871                            OptionElementVector &opt_element_vector) override {
1872     lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1873         GetCommandInterpreter(), lldb::eTypeCategoryNameCompletion, request,
1874         nullptr);
1875   }
1876 
1877 protected:
1878   bool DoExecute(Args &command, CommandReturnObject &result) override {
1879     const size_t argc = command.GetArgumentCount();
1880 
1881     if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) {
1882       result.AppendErrorWithFormat("%s takes arguments and/or a language",
1883                                    m_cmd_name.c_str());
1884       return false;
1885     }
1886 
1887     if (argc == 1 && strcmp(command.GetArgumentAtIndex(0), "*") == 0) {
1888       DataVisualization::Categories::EnableStar();
1889     } else if (argc > 0) {
1890       for (int i = argc - 1; i >= 0; i--) {
1891         const char *typeA = command.GetArgumentAtIndex(i);
1892         ConstString typeCS(typeA);
1893 
1894         if (!typeCS) {
1895           result.AppendError("empty category name not allowed");
1896           return false;
1897         }
1898         DataVisualization::Categories::Enable(typeCS);
1899         lldb::TypeCategoryImplSP cate;
1900         if (DataVisualization::Categories::GetCategory(typeCS, cate) && cate) {
1901           if (cate->GetCount() == 0) {
1902             result.AppendWarning("empty category enabled (typo?)");
1903           }
1904         }
1905       }
1906     }
1907 
1908     if (m_options.m_language != lldb::eLanguageTypeUnknown)
1909       DataVisualization::Categories::Enable(m_options.m_language);
1910 
1911     result.SetStatus(eReturnStatusSuccessFinishResult);
1912     return result.Succeeded();
1913   }
1914 };
1915 
1916 // CommandObjectTypeCategoryDelete
1917 
1918 class CommandObjectTypeCategoryDelete : public CommandObjectParsed {
1919 public:
1920   CommandObjectTypeCategoryDelete(CommandInterpreter &interpreter)
1921       : CommandObjectParsed(interpreter, "type category delete",
1922                             "Delete a category and all associated formatters.",
1923                             nullptr) {
1924     CommandArgumentEntry type_arg;
1925     CommandArgumentData type_style_arg;
1926 
1927     type_style_arg.arg_type = eArgTypeName;
1928     type_style_arg.arg_repetition = eArgRepeatPlus;
1929 
1930     type_arg.push_back(type_style_arg);
1931 
1932     m_arguments.push_back(type_arg);
1933   }
1934 
1935   ~CommandObjectTypeCategoryDelete() override = default;
1936 
1937   void
1938   HandleArgumentCompletion(CompletionRequest &request,
1939                            OptionElementVector &opt_element_vector) override {
1940     lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1941         GetCommandInterpreter(), lldb::eTypeCategoryNameCompletion, request,
1942         nullptr);
1943   }
1944 
1945 protected:
1946   bool DoExecute(Args &command, CommandReturnObject &result) override {
1947     const size_t argc = command.GetArgumentCount();
1948 
1949     if (argc < 1) {
1950       result.AppendErrorWithFormat("%s takes 1 or more arg.\n",
1951                                    m_cmd_name.c_str());
1952       return false;
1953     }
1954 
1955     bool success = true;
1956 
1957     // the order is not relevant here
1958     for (int i = argc - 1; i >= 0; i--) {
1959       const char *typeA = command.GetArgumentAtIndex(i);
1960       ConstString typeCS(typeA);
1961 
1962       if (!typeCS) {
1963         result.AppendError("empty category name not allowed");
1964         return false;
1965       }
1966       if (!DataVisualization::Categories::Delete(typeCS))
1967         success = false; // keep deleting even if we hit an error
1968     }
1969     if (success) {
1970       result.SetStatus(eReturnStatusSuccessFinishResult);
1971       return result.Succeeded();
1972     } else {
1973       result.AppendError("cannot delete one or more categories\n");
1974       return false;
1975     }
1976   }
1977 };
1978 
1979 // CommandObjectTypeCategoryDisable
1980 #define LLDB_OPTIONS_type_category_disable
1981 #include "CommandOptions.inc"
1982 
1983 class CommandObjectTypeCategoryDisable : public CommandObjectParsed {
1984   class CommandOptions : public Options {
1985   public:
1986     CommandOptions() = default;
1987 
1988     ~CommandOptions() override = default;
1989 
1990     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1991                           ExecutionContext *execution_context) override {
1992       Status error;
1993       const int short_option = m_getopt_table[option_idx].val;
1994 
1995       switch (short_option) {
1996       case 'l':
1997         if (!option_arg.empty()) {
1998           m_language = Language::GetLanguageTypeFromString(option_arg);
1999           if (m_language == lldb::eLanguageTypeUnknown)
2000             error.SetErrorStringWithFormat("unrecognized language '%s'",
2001                                            option_arg.str().c_str());
2002         }
2003         break;
2004       default:
2005         llvm_unreachable("Unimplemented option");
2006       }
2007 
2008       return error;
2009     }
2010 
2011     void OptionParsingStarting(ExecutionContext *execution_context) override {
2012       m_language = lldb::eLanguageTypeUnknown;
2013     }
2014 
2015     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2016       return llvm::ArrayRef(g_type_category_disable_options);
2017     }
2018 
2019     // Instance variables to hold the values for command options.
2020 
2021     lldb::LanguageType m_language;
2022   };
2023 
2024   CommandOptions m_options;
2025 
2026   Options *GetOptions() override { return &m_options; }
2027 
2028 public:
2029   CommandObjectTypeCategoryDisable(CommandInterpreter &interpreter)
2030       : CommandObjectParsed(interpreter, "type category disable",
2031                             "Disable a category as a source of formatters.",
2032                             nullptr) {
2033     CommandArgumentEntry type_arg;
2034     CommandArgumentData type_style_arg;
2035 
2036     type_style_arg.arg_type = eArgTypeName;
2037     type_style_arg.arg_repetition = eArgRepeatPlus;
2038 
2039     type_arg.push_back(type_style_arg);
2040 
2041     m_arguments.push_back(type_arg);
2042   }
2043 
2044   ~CommandObjectTypeCategoryDisable() override = default;
2045 
2046   void
2047   HandleArgumentCompletion(CompletionRequest &request,
2048                            OptionElementVector &opt_element_vector) override {
2049     lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
2050         GetCommandInterpreter(), lldb::eTypeCategoryNameCompletion, request,
2051         nullptr);
2052   }
2053 
2054 protected:
2055   bool DoExecute(Args &command, CommandReturnObject &result) override {
2056     const size_t argc = command.GetArgumentCount();
2057 
2058     if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) {
2059       result.AppendErrorWithFormat("%s takes arguments and/or a language",
2060                                    m_cmd_name.c_str());
2061       return false;
2062     }
2063 
2064     if (argc == 1 && strcmp(command.GetArgumentAtIndex(0), "*") == 0) {
2065       DataVisualization::Categories::DisableStar();
2066     } else if (argc > 0) {
2067       // the order is not relevant here
2068       for (int i = argc - 1; i >= 0; i--) {
2069         const char *typeA = command.GetArgumentAtIndex(i);
2070         ConstString typeCS(typeA);
2071 
2072         if (!typeCS) {
2073           result.AppendError("empty category name not allowed");
2074           return false;
2075         }
2076         DataVisualization::Categories::Disable(typeCS);
2077       }
2078     }
2079 
2080     if (m_options.m_language != lldb::eLanguageTypeUnknown)
2081       DataVisualization::Categories::Disable(m_options.m_language);
2082 
2083     result.SetStatus(eReturnStatusSuccessFinishResult);
2084     return result.Succeeded();
2085   }
2086 };
2087 
2088 // CommandObjectTypeCategoryList
2089 
2090 class CommandObjectTypeCategoryList : public CommandObjectParsed {
2091 public:
2092   CommandObjectTypeCategoryList(CommandInterpreter &interpreter)
2093       : CommandObjectParsed(interpreter, "type category list",
2094                             "Provide a list of all existing categories.",
2095                             nullptr) {
2096     CommandArgumentEntry type_arg;
2097     CommandArgumentData type_style_arg;
2098 
2099     type_style_arg.arg_type = eArgTypeName;
2100     type_style_arg.arg_repetition = eArgRepeatOptional;
2101 
2102     type_arg.push_back(type_style_arg);
2103 
2104     m_arguments.push_back(type_arg);
2105   }
2106 
2107   ~CommandObjectTypeCategoryList() override = default;
2108 
2109   void
2110   HandleArgumentCompletion(CompletionRequest &request,
2111                            OptionElementVector &opt_element_vector) override {
2112     if (request.GetCursorIndex())
2113       return;
2114     lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
2115         GetCommandInterpreter(), lldb::eTypeCategoryNameCompletion, request,
2116         nullptr);
2117   }
2118 
2119 protected:
2120   bool DoExecute(Args &command, CommandReturnObject &result) override {
2121     const size_t argc = command.GetArgumentCount();
2122 
2123     std::unique_ptr<RegularExpression> regex;
2124 
2125     if (argc == 1) {
2126       const char *arg = command.GetArgumentAtIndex(0);
2127       regex = std::make_unique<RegularExpression>(arg);
2128       if (!regex->IsValid()) {
2129         result.AppendErrorWithFormat(
2130             "syntax error in category regular expression '%s'", arg);
2131         return false;
2132       }
2133     } else if (argc != 0) {
2134       result.AppendErrorWithFormat("%s takes 0 or one arg.\n",
2135                                    m_cmd_name.c_str());
2136       return false;
2137     }
2138 
2139     DataVisualization::Categories::ForEach(
2140         [&regex, &result](const lldb::TypeCategoryImplSP &category_sp) -> bool {
2141           if (regex) {
2142             bool escape = true;
2143             if (regex->GetText() == category_sp->GetName()) {
2144               escape = false;
2145             } else if (regex->Execute(category_sp->GetName())) {
2146               escape = false;
2147             }
2148 
2149             if (escape)
2150               return true;
2151           }
2152 
2153           result.GetOutputStream().Printf(
2154               "Category: %s\n", category_sp->GetDescription().c_str());
2155 
2156           return true;
2157         });
2158 
2159     result.SetStatus(eReturnStatusSuccessFinishResult);
2160     return result.Succeeded();
2161   }
2162 };
2163 
2164 // CommandObjectTypeFilterList
2165 
2166 class CommandObjectTypeFilterList
2167     : public CommandObjectTypeFormatterList<TypeFilterImpl> {
2168 public:
2169   CommandObjectTypeFilterList(CommandInterpreter &interpreter)
2170       : CommandObjectTypeFormatterList(interpreter, "type filter list",
2171                                        "Show a list of current filters.") {}
2172 };
2173 
2174 #if LLDB_ENABLE_PYTHON
2175 
2176 // CommandObjectTypeSynthList
2177 
2178 class CommandObjectTypeSynthList
2179     : public CommandObjectTypeFormatterList<SyntheticChildren> {
2180 public:
2181   CommandObjectTypeSynthList(CommandInterpreter &interpreter)
2182       : CommandObjectTypeFormatterList(
2183             interpreter, "type synthetic list",
2184             "Show a list of current synthetic providers.") {}
2185 };
2186 
2187 #endif
2188 
2189 // CommandObjectTypeFilterDelete
2190 
2191 class CommandObjectTypeFilterDelete : public CommandObjectTypeFormatterDelete {
2192 public:
2193   CommandObjectTypeFilterDelete(CommandInterpreter &interpreter)
2194       : CommandObjectTypeFormatterDelete(
2195             interpreter, eFormatCategoryItemFilter) {}
2196 
2197   ~CommandObjectTypeFilterDelete() override = default;
2198 };
2199 
2200 #if LLDB_ENABLE_PYTHON
2201 
2202 // CommandObjectTypeSynthDelete
2203 
2204 class CommandObjectTypeSynthDelete : public CommandObjectTypeFormatterDelete {
2205 public:
2206   CommandObjectTypeSynthDelete(CommandInterpreter &interpreter)
2207       : CommandObjectTypeFormatterDelete(
2208             interpreter, eFormatCategoryItemSynth) {}
2209 
2210   ~CommandObjectTypeSynthDelete() override = default;
2211 };
2212 
2213 #endif
2214 
2215 // CommandObjectTypeFilterClear
2216 
2217 class CommandObjectTypeFilterClear : public CommandObjectTypeFormatterClear {
2218 public:
2219   CommandObjectTypeFilterClear(CommandInterpreter &interpreter)
2220       : CommandObjectTypeFormatterClear(interpreter, eFormatCategoryItemFilter,
2221                                         "type filter clear",
2222                                         "Delete all existing filter.") {}
2223 };
2224 
2225 #if LLDB_ENABLE_PYTHON
2226 // CommandObjectTypeSynthClear
2227 
2228 class CommandObjectTypeSynthClear : public CommandObjectTypeFormatterClear {
2229 public:
2230   CommandObjectTypeSynthClear(CommandInterpreter &interpreter)
2231       : CommandObjectTypeFormatterClear(
2232             interpreter, eFormatCategoryItemSynth, "type synthetic clear",
2233             "Delete all existing synthetic providers.") {}
2234 };
2235 
2236 bool CommandObjectTypeSynthAdd::Execute_HandwritePython(
2237     Args &command, CommandReturnObject &result) {
2238   auto options = std::make_unique<SynthAddOptions>(
2239       m_options.m_skip_pointers, m_options.m_skip_references,
2240       m_options.m_cascade, m_options.m_match_type, m_options.m_category);
2241 
2242   for (auto &entry : command.entries()) {
2243     if (entry.ref().empty()) {
2244       result.AppendError("empty typenames not allowed");
2245       return false;
2246     }
2247 
2248     options->m_target_types << std::string(entry.ref());
2249   }
2250 
2251   m_interpreter.GetPythonCommandsFromIOHandler(
2252       "    ",             // Prompt
2253       *this,              // IOHandlerDelegate
2254       options.release()); // Baton for the "io_handler" that will be passed back
2255                           // into our IOHandlerDelegate functions
2256   result.SetStatus(eReturnStatusSuccessFinishNoResult);
2257   return result.Succeeded();
2258 }
2259 
2260 bool CommandObjectTypeSynthAdd::Execute_PythonClass(
2261     Args &command, CommandReturnObject &result) {
2262   const size_t argc = command.GetArgumentCount();
2263 
2264   if (argc < 1) {
2265     result.AppendErrorWithFormat("%s takes one or more args.\n",
2266                                  m_cmd_name.c_str());
2267     return false;
2268   }
2269 
2270   if (m_options.m_class_name.empty() && !m_options.m_input_python) {
2271     result.AppendErrorWithFormat("%s needs either a Python class name or -P to "
2272                                  "directly input Python code.\n",
2273                                  m_cmd_name.c_str());
2274     return false;
2275   }
2276 
2277   SyntheticChildrenSP entry;
2278 
2279   ScriptedSyntheticChildren *impl = new ScriptedSyntheticChildren(
2280       SyntheticChildren::Flags()
2281           .SetCascades(m_options.m_cascade)
2282           .SetSkipPointers(m_options.m_skip_pointers)
2283           .SetSkipReferences(m_options.m_skip_references),
2284       m_options.m_class_name.c_str());
2285 
2286   entry.reset(impl);
2287 
2288   ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
2289 
2290   if (interpreter &&
2291       !interpreter->CheckObjectExists(impl->GetPythonClassName()))
2292     result.AppendWarning("The provided class does not exist - please define it "
2293                          "before attempting to use this synthetic provider");
2294 
2295   // now I have a valid provider, let's add it to every type
2296 
2297   lldb::TypeCategoryImplSP category;
2298   DataVisualization::Categories::GetCategory(
2299       ConstString(m_options.m_category.c_str()), category);
2300 
2301   Status error;
2302 
2303   for (auto &arg_entry : command.entries()) {
2304     if (arg_entry.ref().empty()) {
2305       result.AppendError("empty typenames not allowed");
2306       return false;
2307     }
2308 
2309     ConstString typeCS(arg_entry.ref());
2310     if (!AddSynth(typeCS, entry, m_options.m_match_type, m_options.m_category,
2311                   &error)) {
2312       result.AppendError(error.AsCString());
2313       return false;
2314     }
2315   }
2316 
2317   result.SetStatus(eReturnStatusSuccessFinishNoResult);
2318   return result.Succeeded();
2319 }
2320 
2321 CommandObjectTypeSynthAdd::CommandObjectTypeSynthAdd(
2322     CommandInterpreter &interpreter)
2323     : CommandObjectParsed(interpreter, "type synthetic add",
2324                           "Add a new synthetic provider for a type.", nullptr),
2325       IOHandlerDelegateMultiline("DONE"), m_options() {
2326   CommandArgumentEntry type_arg;
2327   CommandArgumentData type_style_arg;
2328 
2329   type_style_arg.arg_type = eArgTypeName;
2330   type_style_arg.arg_repetition = eArgRepeatPlus;
2331 
2332   type_arg.push_back(type_style_arg);
2333 
2334   m_arguments.push_back(type_arg);
2335 }
2336 
2337 bool CommandObjectTypeSynthAdd::AddSynth(ConstString type_name,
2338                                          SyntheticChildrenSP entry,
2339                                          FormatterMatchType match_type,
2340                                          std::string category_name,
2341                                          Status *error) {
2342   lldb::TypeCategoryImplSP category;
2343   DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()),
2344                                              category);
2345 
2346   if (match_type == eFormatterMatchExact) {
2347     if (FixArrayTypeNameWithRegex(type_name))
2348       match_type = eFormatterMatchRegex;
2349   }
2350 
2351   // Only check for conflicting filters in the same category if `type_name` is
2352   // an actual type name. Matching a regex string against registered regexes
2353   // doesn't work.
2354   if (match_type == eFormatterMatchExact) {
2355     // It's not generally possible to get a type object here. For example, this
2356     // command can be run before loading any binaries. Do just a best-effort
2357     // name-based lookup here to try to prevent conflicts.
2358     FormattersMatchCandidate candidate_type(type_name, nullptr, TypeImpl(),
2359                                             FormattersMatchCandidate::Flags());
2360     if (category->AnyMatches(candidate_type, eFormatCategoryItemFilter,
2361                              false)) {
2362       if (error)
2363         error->SetErrorStringWithFormat("cannot add synthetic for type %s when "
2364                                         "filter is defined in same category!",
2365                                         type_name.AsCString());
2366       return false;
2367     }
2368   }
2369 
2370   if (match_type == eFormatterMatchRegex) {
2371     RegularExpression typeRX(type_name.GetStringRef());
2372     if (!typeRX.IsValid()) {
2373       if (error)
2374         error->SetErrorString(
2375             "regex format error (maybe this is not really a regex?)");
2376       return false;
2377     }
2378   }
2379 
2380   if (match_type == eFormatterMatchCallback) {
2381     const char *function_name = type_name.AsCString();
2382     ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
2383     if (interpreter && !interpreter->CheckObjectExists(function_name)) {
2384       error->SetErrorStringWithFormat(
2385           "The provided recognizer function \"%s\" does not exist - "
2386           "please define it before attempting to use this summary.\n",
2387           function_name);
2388       return false;
2389     }
2390   }
2391 
2392   category->AddTypeSynthetic(type_name.GetStringRef(), match_type, entry);
2393   return true;
2394 }
2395 
2396 #endif
2397 #define LLDB_OPTIONS_type_filter_add
2398 #include "CommandOptions.inc"
2399 
2400 class CommandObjectTypeFilterAdd : public CommandObjectParsed {
2401 private:
2402   class CommandOptions : public Options {
2403     typedef std::vector<std::string> option_vector;
2404 
2405   public:
2406     CommandOptions() = default;
2407 
2408     ~CommandOptions() override = default;
2409 
2410     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2411                           ExecutionContext *execution_context) override {
2412       Status error;
2413       const int short_option = m_getopt_table[option_idx].val;
2414       bool success;
2415 
2416       switch (short_option) {
2417       case 'C':
2418         m_cascade = OptionArgParser::ToBoolean(option_arg, true, &success);
2419         if (!success)
2420           error.SetErrorStringWithFormat("invalid value for cascade: %s",
2421                                          option_arg.str().c_str());
2422         break;
2423       case 'c':
2424         m_expr_paths.push_back(std::string(option_arg));
2425         has_child_list = true;
2426         break;
2427       case 'p':
2428         m_skip_pointers = true;
2429         break;
2430       case 'r':
2431         m_skip_references = true;
2432         break;
2433       case 'w':
2434         m_category = std::string(option_arg);
2435         break;
2436       case 'x':
2437         m_regex = true;
2438         break;
2439       default:
2440         llvm_unreachable("Unimplemented option");
2441       }
2442 
2443       return error;
2444     }
2445 
2446     void OptionParsingStarting(ExecutionContext *execution_context) override {
2447       m_cascade = true;
2448       m_skip_pointers = false;
2449       m_skip_references = false;
2450       m_category = "default";
2451       m_expr_paths.clear();
2452       has_child_list = false;
2453       m_regex = false;
2454     }
2455 
2456     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2457       return llvm::ArrayRef(g_type_filter_add_options);
2458     }
2459 
2460     // Instance variables to hold the values for command options.
2461 
2462     bool m_cascade;
2463     bool m_skip_references;
2464     bool m_skip_pointers;
2465     bool m_input_python;
2466     option_vector m_expr_paths;
2467     std::string m_category;
2468     bool has_child_list;
2469     bool m_regex;
2470 
2471     typedef option_vector::iterator ExpressionPathsIterator;
2472   };
2473 
2474   CommandOptions m_options;
2475 
2476   Options *GetOptions() override { return &m_options; }
2477 
2478   enum FilterFormatType { eRegularFilter, eRegexFilter };
2479 
2480   bool AddFilter(ConstString type_name, TypeFilterImplSP entry,
2481                  FilterFormatType type, std::string category_name,
2482                  Status *error) {
2483     lldb::TypeCategoryImplSP category;
2484     DataVisualization::Categories::GetCategory(
2485         ConstString(category_name.c_str()), category);
2486 
2487     if (type == eRegularFilter) {
2488       if (FixArrayTypeNameWithRegex(type_name))
2489         type = eRegexFilter;
2490     }
2491 
2492     // Only check for conflicting synthetic child providers in the same category
2493     // if `type_name` is an actual type name. Matching a regex string against
2494     // registered regexes doesn't work.
2495     if (type == eRegularFilter) {
2496       // It's not generally possible to get a type object here. For example,
2497       // this command can be run before loading any binaries. Do just a
2498       // best-effort name-based lookup here to try to prevent conflicts.
2499       FormattersMatchCandidate candidate_type(
2500           type_name, nullptr, TypeImpl(), FormattersMatchCandidate::Flags());
2501       lldb::SyntheticChildrenSP entry;
2502       if (category->AnyMatches(candidate_type, eFormatCategoryItemSynth,
2503                                false)) {
2504         if (error)
2505           error->SetErrorStringWithFormat("cannot add filter for type %s when "
2506                                           "synthetic is defined in same "
2507                                           "category!",
2508                                           type_name.AsCString());
2509         return false;
2510       }
2511     }
2512 
2513     FormatterMatchType match_type = eFormatterMatchExact;
2514     if (type == eRegexFilter) {
2515       match_type = eFormatterMatchRegex;
2516       RegularExpression typeRX(type_name.GetStringRef());
2517       if (!typeRX.IsValid()) {
2518         if (error)
2519           error->SetErrorString(
2520               "regex format error (maybe this is not really a regex?)");
2521         return false;
2522       }
2523     }
2524     category->AddTypeFilter(type_name.GetStringRef(), match_type, entry);
2525     return true;
2526   }
2527 
2528 public:
2529   CommandObjectTypeFilterAdd(CommandInterpreter &interpreter)
2530       : CommandObjectParsed(interpreter, "type filter add",
2531                             "Add a new filter for a type.", nullptr) {
2532     CommandArgumentEntry type_arg;
2533     CommandArgumentData type_style_arg;
2534 
2535     type_style_arg.arg_type = eArgTypeName;
2536     type_style_arg.arg_repetition = eArgRepeatPlus;
2537 
2538     type_arg.push_back(type_style_arg);
2539 
2540     m_arguments.push_back(type_arg);
2541 
2542     SetHelpLong(
2543         R"(
2544 The following examples of 'type filter add' refer to this code snippet for context:
2545 
2546     class Foo {
2547         int a;
2548         int b;
2549         int c;
2550         int d;
2551         int e;
2552         int f;
2553         int g;
2554         int h;
2555         int i;
2556     }
2557     Foo my_foo;
2558 
2559 Adding a simple filter:
2560 
2561 (lldb) type filter add --child a --child g Foo
2562 (lldb) frame variable my_foo
2563 
2564 )"
2565         "Produces output where only a and g are displayed.  Other children of my_foo \
2566 (b, c, d, e, f, h and i) are available by asking for them explicitly:"
2567         R"(
2568 
2569 (lldb) frame variable my_foo.b my_foo.c my_foo.i
2570 
2571 )"
2572         "The formatting option --raw on frame variable bypasses the filter, showing \
2573 all children of my_foo as if no filter was defined:"
2574         R"(
2575 
2576 (lldb) frame variable my_foo --raw)");
2577   }
2578 
2579   ~CommandObjectTypeFilterAdd() override = default;
2580 
2581 protected:
2582   bool DoExecute(Args &command, CommandReturnObject &result) override {
2583     const size_t argc = command.GetArgumentCount();
2584 
2585     if (argc < 1) {
2586       result.AppendErrorWithFormat("%s takes one or more args.\n",
2587                                    m_cmd_name.c_str());
2588       return false;
2589     }
2590 
2591     if (m_options.m_expr_paths.empty()) {
2592       result.AppendErrorWithFormat("%s needs one or more children.\n",
2593                                    m_cmd_name.c_str());
2594       return false;
2595     }
2596 
2597     TypeFilterImplSP entry(new TypeFilterImpl(
2598         SyntheticChildren::Flags()
2599             .SetCascades(m_options.m_cascade)
2600             .SetSkipPointers(m_options.m_skip_pointers)
2601             .SetSkipReferences(m_options.m_skip_references)));
2602 
2603     // go through the expression paths
2604     CommandOptions::ExpressionPathsIterator begin,
2605         end = m_options.m_expr_paths.end();
2606 
2607     for (begin = m_options.m_expr_paths.begin(); begin != end; begin++)
2608       entry->AddExpressionPath(*begin);
2609 
2610     // now I have a valid provider, let's add it to every type
2611 
2612     lldb::TypeCategoryImplSP category;
2613     DataVisualization::Categories::GetCategory(
2614         ConstString(m_options.m_category.c_str()), category);
2615 
2616     Status error;
2617 
2618     WarnOnPotentialUnquotedUnsignedType(command, result);
2619 
2620     for (auto &arg_entry : command.entries()) {
2621       if (arg_entry.ref().empty()) {
2622         result.AppendError("empty typenames not allowed");
2623         return false;
2624       }
2625 
2626       ConstString typeCS(arg_entry.ref());
2627       if (!AddFilter(typeCS, entry,
2628                      m_options.m_regex ? eRegexFilter : eRegularFilter,
2629                      m_options.m_category, &error)) {
2630         result.AppendError(error.AsCString());
2631         return false;
2632       }
2633     }
2634 
2635     result.SetStatus(eReturnStatusSuccessFinishNoResult);
2636     return result.Succeeded();
2637   }
2638 };
2639 
2640 // "type lookup"
2641 #define LLDB_OPTIONS_type_lookup
2642 #include "CommandOptions.inc"
2643 
2644 class CommandObjectTypeLookup : public CommandObjectRaw {
2645 protected:
2646   // this function is allowed to do a more aggressive job at guessing languages
2647   // than the expression parser is comfortable with - so leave the original
2648   // call alone and add one that is specific to type lookup
2649   lldb::LanguageType GuessLanguage(StackFrame *frame) {
2650     lldb::LanguageType lang_type = lldb::eLanguageTypeUnknown;
2651 
2652     if (!frame)
2653       return lang_type;
2654 
2655     lang_type = frame->GuessLanguage();
2656     if (lang_type != lldb::eLanguageTypeUnknown)
2657       return lang_type;
2658 
2659     Symbol *s = frame->GetSymbolContext(eSymbolContextSymbol).symbol;
2660     if (s)
2661       lang_type = s->GetMangled().GuessLanguage();
2662 
2663     return lang_type;
2664   }
2665 
2666   class CommandOptions : public OptionGroup {
2667   public:
2668     CommandOptions() = default;
2669 
2670     ~CommandOptions() override = default;
2671 
2672     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2673       return llvm::ArrayRef(g_type_lookup_options);
2674     }
2675 
2676     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
2677                           ExecutionContext *execution_context) override {
2678       Status error;
2679 
2680       const int short_option = g_type_lookup_options[option_idx].short_option;
2681 
2682       switch (short_option) {
2683       case 'h':
2684         m_show_help = true;
2685         break;
2686 
2687       case 'l':
2688         m_language = Language::GetLanguageTypeFromString(option_value);
2689         break;
2690 
2691       default:
2692         llvm_unreachable("Unimplemented option");
2693       }
2694 
2695       return error;
2696     }
2697 
2698     void OptionParsingStarting(ExecutionContext *execution_context) override {
2699       m_show_help = false;
2700       m_language = eLanguageTypeUnknown;
2701     }
2702 
2703     // Options table: Required for subclasses of Options.
2704 
2705     bool m_show_help = false;
2706     lldb::LanguageType m_language = eLanguageTypeUnknown;
2707   };
2708 
2709   OptionGroupOptions m_option_group;
2710   CommandOptions m_command_options;
2711 
2712 public:
2713   CommandObjectTypeLookup(CommandInterpreter &interpreter)
2714       : CommandObjectRaw(interpreter, "type lookup",
2715                          "Lookup types and declarations in the current target, "
2716                          "following language-specific naming conventions.",
2717                          "type lookup <type-specifier>",
2718                          eCommandRequiresTarget) {
2719     m_option_group.Append(&m_command_options);
2720     m_option_group.Finalize();
2721   }
2722 
2723   ~CommandObjectTypeLookup() override = default;
2724 
2725   Options *GetOptions() override { return &m_option_group; }
2726 
2727   llvm::StringRef GetHelpLong() override {
2728     if (!m_cmd_help_long.empty())
2729       return m_cmd_help_long;
2730 
2731     StreamString stream;
2732     Language::ForEach([&](Language *lang) {
2733       if (const char *help = lang->GetLanguageSpecificTypeLookupHelp())
2734         stream.Printf("%s\n", help);
2735       return true;
2736     });
2737 
2738     m_cmd_help_long = std::string(stream.GetString());
2739     return m_cmd_help_long;
2740   }
2741 
2742   bool DoExecute(llvm::StringRef raw_command_line,
2743                  CommandReturnObject &result) override {
2744     if (raw_command_line.empty()) {
2745       result.AppendError(
2746           "type lookup cannot be invoked without a type name as argument");
2747       return false;
2748     }
2749 
2750     auto exe_ctx = GetCommandInterpreter().GetExecutionContext();
2751     m_option_group.NotifyOptionParsingStarting(&exe_ctx);
2752 
2753     OptionsWithRaw args(raw_command_line);
2754     const char *name_of_type = args.GetRawPart().c_str();
2755 
2756     if (args.HasArgs())
2757       if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group,
2758                                  exe_ctx))
2759         return false;
2760 
2761     ExecutionContextScope *best_scope = exe_ctx.GetBestExecutionContextScope();
2762 
2763     bool any_found = false;
2764 
2765     std::vector<Language *> languages;
2766 
2767     bool is_global_search = false;
2768     LanguageType guessed_language = lldb::eLanguageTypeUnknown;
2769 
2770     if ((is_global_search =
2771              (m_command_options.m_language == eLanguageTypeUnknown))) {
2772       Language::ForEach([&](Language *lang) {
2773         languages.push_back(lang);
2774         return true;
2775       });
2776     } else {
2777       languages.push_back(Language::FindPlugin(m_command_options.m_language));
2778     }
2779 
2780     // This is not the most efficient way to do this, but we support very few
2781     // languages so the cost of the sort is going to be dwarfed by the actual
2782     // lookup anyway
2783     if (StackFrame *frame = m_exe_ctx.GetFramePtr()) {
2784       guessed_language = GuessLanguage(frame);
2785       if (guessed_language != eLanguageTypeUnknown) {
2786         llvm::sort(
2787             languages.begin(), languages.end(),
2788             [guessed_language](Language *lang1, Language *lang2) -> bool {
2789               if (!lang1 || !lang2)
2790                 return false;
2791               LanguageType lt1 = lang1->GetLanguageType();
2792               LanguageType lt2 = lang2->GetLanguageType();
2793               if (lt1 == guessed_language)
2794                 return true; // make the selected frame's language come first
2795               if (lt2 == guessed_language)
2796                 return false; // make the selected frame's language come first
2797               return (lt1 < lt2); // normal comparison otherwise
2798             });
2799       }
2800     }
2801 
2802     bool is_first_language = true;
2803 
2804     for (Language *language : languages) {
2805       if (!language)
2806         continue;
2807 
2808       if (auto scavenger = language->GetTypeScavenger()) {
2809         Language::TypeScavenger::ResultSet search_results;
2810         if (scavenger->Find(best_scope, name_of_type, search_results) > 0) {
2811           for (const auto &search_result : search_results) {
2812             if (search_result && search_result->IsValid()) {
2813               any_found = true;
2814               search_result->DumpToStream(result.GetOutputStream(),
2815                                           this->m_command_options.m_show_help);
2816             }
2817           }
2818         }
2819       }
2820       // this is "type lookup SomeName" and we did find a match, so get out
2821       if (any_found && is_global_search)
2822         break;
2823       else if (is_first_language && is_global_search &&
2824                guessed_language != lldb::eLanguageTypeUnknown) {
2825         is_first_language = false;
2826         result.GetOutputStream().Printf(
2827             "no type was found in the current language %s matching '%s'; "
2828             "performing a global search across all languages\n",
2829             Language::GetNameForLanguageType(guessed_language), name_of_type);
2830       }
2831     }
2832 
2833     if (!any_found)
2834       result.AppendMessageWithFormat("no type was found matching '%s'\n",
2835                                      name_of_type);
2836 
2837     result.SetStatus(any_found ? lldb::eReturnStatusSuccessFinishResult
2838                                : lldb::eReturnStatusSuccessFinishNoResult);
2839     return true;
2840   }
2841 };
2842 
2843 template <typename FormatterType>
2844 class CommandObjectFormatterInfo : public CommandObjectRaw {
2845 public:
2846   typedef std::function<typename FormatterType::SharedPointer(ValueObject &)>
2847       DiscoveryFunction;
2848   CommandObjectFormatterInfo(CommandInterpreter &interpreter,
2849                              const char *formatter_name,
2850                              DiscoveryFunction discovery_func)
2851       : CommandObjectRaw(interpreter, "", "", "", eCommandRequiresFrame),
2852         m_formatter_name(formatter_name ? formatter_name : ""),
2853         m_discovery_function(discovery_func) {
2854     StreamString name;
2855     name.Printf("type %s info", formatter_name);
2856     SetCommandName(name.GetString());
2857     StreamString help;
2858     help.Printf("This command evaluates the provided expression and shows "
2859                 "which %s is applied to the resulting value (if any).",
2860                 formatter_name);
2861     SetHelp(help.GetString());
2862     StreamString syntax;
2863     syntax.Printf("type %s info <expr>", formatter_name);
2864     SetSyntax(syntax.GetString());
2865   }
2866 
2867   ~CommandObjectFormatterInfo() override = default;
2868 
2869 protected:
2870   bool DoExecute(llvm::StringRef command,
2871                  CommandReturnObject &result) override {
2872     TargetSP target_sp = GetDebugger().GetSelectedTarget();
2873     Thread *thread = GetDefaultThread();
2874     if (!thread) {
2875       result.AppendError("no default thread");
2876       return false;
2877     }
2878 
2879     StackFrameSP frame_sp =
2880         thread->GetSelectedFrame(DoNoSelectMostRelevantFrame);
2881     ValueObjectSP result_valobj_sp;
2882     EvaluateExpressionOptions options;
2883     lldb::ExpressionResults expr_result = target_sp->EvaluateExpression(
2884         command, frame_sp.get(), result_valobj_sp, options);
2885     if (expr_result == eExpressionCompleted && result_valobj_sp) {
2886       result_valobj_sp =
2887           result_valobj_sp->GetQualifiedRepresentationIfAvailable(
2888               target_sp->GetPreferDynamicValue(),
2889               target_sp->GetEnableSyntheticValue());
2890       typename FormatterType::SharedPointer formatter_sp =
2891           m_discovery_function(*result_valobj_sp);
2892       if (formatter_sp) {
2893         std::string description(formatter_sp->GetDescription());
2894         result.GetOutputStream()
2895             << m_formatter_name << " applied to ("
2896             << result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>")
2897             << ") " << command << " is: " << description << "\n";
2898         result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
2899       } else {
2900         result.GetOutputStream()
2901             << "no " << m_formatter_name << " applies to ("
2902             << result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>")
2903             << ") " << command << "\n";
2904         result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
2905       }
2906       return true;
2907     } else {
2908       result.AppendError("failed to evaluate expression");
2909       return false;
2910     }
2911   }
2912 
2913 private:
2914   std::string m_formatter_name;
2915   DiscoveryFunction m_discovery_function;
2916 };
2917 
2918 class CommandObjectTypeFormat : public CommandObjectMultiword {
2919 public:
2920   CommandObjectTypeFormat(CommandInterpreter &interpreter)
2921       : CommandObjectMultiword(
2922             interpreter, "type format",
2923             "Commands for customizing value display formats.",
2924             "type format [<sub-command-options>] ") {
2925     LoadSubCommand(
2926         "add", CommandObjectSP(new CommandObjectTypeFormatAdd(interpreter)));
2927     LoadSubCommand("clear", CommandObjectSP(
2928                                 new CommandObjectTypeFormatClear(interpreter)));
2929     LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFormatDelete(
2930                                  interpreter)));
2931     LoadSubCommand(
2932         "list", CommandObjectSP(new CommandObjectTypeFormatList(interpreter)));
2933     LoadSubCommand(
2934         "info", CommandObjectSP(new CommandObjectFormatterInfo<TypeFormatImpl>(
2935                     interpreter, "format",
2936                     [](ValueObject &valobj) -> TypeFormatImpl::SharedPointer {
2937                       return valobj.GetValueFormat();
2938                     })));
2939   }
2940 
2941   ~CommandObjectTypeFormat() override = default;
2942 };
2943 
2944 #if LLDB_ENABLE_PYTHON
2945 
2946 class CommandObjectTypeSynth : public CommandObjectMultiword {
2947 public:
2948   CommandObjectTypeSynth(CommandInterpreter &interpreter)
2949       : CommandObjectMultiword(
2950             interpreter, "type synthetic",
2951             "Commands for operating on synthetic type representations.",
2952             "type synthetic [<sub-command-options>] ") {
2953     LoadSubCommand("add",
2954                    CommandObjectSP(new CommandObjectTypeSynthAdd(interpreter)));
2955     LoadSubCommand(
2956         "clear", CommandObjectSP(new CommandObjectTypeSynthClear(interpreter)));
2957     LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSynthDelete(
2958                                  interpreter)));
2959     LoadSubCommand(
2960         "list", CommandObjectSP(new CommandObjectTypeSynthList(interpreter)));
2961     LoadSubCommand(
2962         "info",
2963         CommandObjectSP(new CommandObjectFormatterInfo<SyntheticChildren>(
2964             interpreter, "synthetic",
2965             [](ValueObject &valobj) -> SyntheticChildren::SharedPointer {
2966               return valobj.GetSyntheticChildren();
2967             })));
2968   }
2969 
2970   ~CommandObjectTypeSynth() override = default;
2971 };
2972 
2973 #endif
2974 
2975 class CommandObjectTypeFilter : public CommandObjectMultiword {
2976 public:
2977   CommandObjectTypeFilter(CommandInterpreter &interpreter)
2978       : CommandObjectMultiword(interpreter, "type filter",
2979                                "Commands for operating on type filters.",
2980                                "type filter [<sub-command-options>] ") {
2981     LoadSubCommand(
2982         "add", CommandObjectSP(new CommandObjectTypeFilterAdd(interpreter)));
2983     LoadSubCommand("clear", CommandObjectSP(
2984                                 new CommandObjectTypeFilterClear(interpreter)));
2985     LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFilterDelete(
2986                                  interpreter)));
2987     LoadSubCommand(
2988         "list", CommandObjectSP(new CommandObjectTypeFilterList(interpreter)));
2989   }
2990 
2991   ~CommandObjectTypeFilter() override = default;
2992 };
2993 
2994 class CommandObjectTypeCategory : public CommandObjectMultiword {
2995 public:
2996   CommandObjectTypeCategory(CommandInterpreter &interpreter)
2997       : CommandObjectMultiword(interpreter, "type category",
2998                                "Commands for operating on type categories.",
2999                                "type category [<sub-command-options>] ") {
3000     LoadSubCommand(
3001         "define",
3002         CommandObjectSP(new CommandObjectTypeCategoryDefine(interpreter)));
3003     LoadSubCommand(
3004         "enable",
3005         CommandObjectSP(new CommandObjectTypeCategoryEnable(interpreter)));
3006     LoadSubCommand(
3007         "disable",
3008         CommandObjectSP(new CommandObjectTypeCategoryDisable(interpreter)));
3009     LoadSubCommand(
3010         "delete",
3011         CommandObjectSP(new CommandObjectTypeCategoryDelete(interpreter)));
3012     LoadSubCommand("list", CommandObjectSP(
3013                                new CommandObjectTypeCategoryList(interpreter)));
3014   }
3015 
3016   ~CommandObjectTypeCategory() override = default;
3017 };
3018 
3019 class CommandObjectTypeSummary : public CommandObjectMultiword {
3020 public:
3021   CommandObjectTypeSummary(CommandInterpreter &interpreter)
3022       : CommandObjectMultiword(
3023             interpreter, "type summary",
3024             "Commands for editing variable summary display options.",
3025             "type summary [<sub-command-options>] ") {
3026     LoadSubCommand(
3027         "add", CommandObjectSP(new CommandObjectTypeSummaryAdd(interpreter)));
3028     LoadSubCommand("clear", CommandObjectSP(new CommandObjectTypeSummaryClear(
3029                                 interpreter)));
3030     LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSummaryDelete(
3031                                  interpreter)));
3032     LoadSubCommand(
3033         "list", CommandObjectSP(new CommandObjectTypeSummaryList(interpreter)));
3034     LoadSubCommand(
3035         "info", CommandObjectSP(new CommandObjectFormatterInfo<TypeSummaryImpl>(
3036                     interpreter, "summary",
3037                     [](ValueObject &valobj) -> TypeSummaryImpl::SharedPointer {
3038                       return valobj.GetSummaryFormat();
3039                     })));
3040   }
3041 
3042   ~CommandObjectTypeSummary() override = default;
3043 };
3044 
3045 // CommandObjectType
3046 
3047 CommandObjectType::CommandObjectType(CommandInterpreter &interpreter)
3048     : CommandObjectMultiword(interpreter, "type",
3049                              "Commands for operating on the type system.",
3050                              "type [<sub-command-options>]") {
3051   LoadSubCommand("category",
3052                  CommandObjectSP(new CommandObjectTypeCategory(interpreter)));
3053   LoadSubCommand("filter",
3054                  CommandObjectSP(new CommandObjectTypeFilter(interpreter)));
3055   LoadSubCommand("format",
3056                  CommandObjectSP(new CommandObjectTypeFormat(interpreter)));
3057   LoadSubCommand("summary",
3058                  CommandObjectSP(new CommandObjectTypeSummary(interpreter)));
3059 #if LLDB_ENABLE_PYTHON
3060   LoadSubCommand("synthetic",
3061                  CommandObjectSP(new CommandObjectTypeSynth(interpreter)));
3062 #endif
3063   LoadSubCommand("lookup",
3064                  CommandObjectSP(new CommandObjectTypeLookup(interpreter)));
3065 }
3066 
3067 CommandObjectType::~CommandObjectType() = default;
3068