xref: /llvm-project/lldb/source/Commands/CommandObjectType.cpp (revision 79d5d9a0824ddcd5493a451e5009dd6393646e51)
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 // CommandObjectTypeSynthList
2175 
2176 class CommandObjectTypeSynthList
2177     : public CommandObjectTypeFormatterList<SyntheticChildren> {
2178 public:
2179   CommandObjectTypeSynthList(CommandInterpreter &interpreter)
2180       : CommandObjectTypeFormatterList(
2181             interpreter, "type synthetic list",
2182             "Show a list of current synthetic providers.") {}
2183 };
2184 
2185 // CommandObjectTypeFilterDelete
2186 
2187 class CommandObjectTypeFilterDelete : public CommandObjectTypeFormatterDelete {
2188 public:
2189   CommandObjectTypeFilterDelete(CommandInterpreter &interpreter)
2190       : CommandObjectTypeFormatterDelete(
2191             interpreter, eFormatCategoryItemFilter) {}
2192 
2193   ~CommandObjectTypeFilterDelete() override = default;
2194 };
2195 
2196 // CommandObjectTypeSynthDelete
2197 
2198 class CommandObjectTypeSynthDelete : public CommandObjectTypeFormatterDelete {
2199 public:
2200   CommandObjectTypeSynthDelete(CommandInterpreter &interpreter)
2201       : CommandObjectTypeFormatterDelete(
2202             interpreter, eFormatCategoryItemSynth) {}
2203 
2204   ~CommandObjectTypeSynthDelete() override = default;
2205 };
2206 
2207 
2208 // CommandObjectTypeFilterClear
2209 
2210 class CommandObjectTypeFilterClear : public CommandObjectTypeFormatterClear {
2211 public:
2212   CommandObjectTypeFilterClear(CommandInterpreter &interpreter)
2213       : CommandObjectTypeFormatterClear(interpreter, eFormatCategoryItemFilter,
2214                                         "type filter clear",
2215                                         "Delete all existing filter.") {}
2216 };
2217 
2218 // CommandObjectTypeSynthClear
2219 
2220 class CommandObjectTypeSynthClear : public CommandObjectTypeFormatterClear {
2221 public:
2222   CommandObjectTypeSynthClear(CommandInterpreter &interpreter)
2223       : CommandObjectTypeFormatterClear(
2224             interpreter, eFormatCategoryItemSynth, "type synthetic clear",
2225             "Delete all existing synthetic providers.") {}
2226 };
2227 
2228 bool CommandObjectTypeSynthAdd::Execute_HandwritePython(
2229     Args &command, CommandReturnObject &result) {
2230   auto options = std::make_unique<SynthAddOptions>(
2231       m_options.m_skip_pointers, m_options.m_skip_references,
2232       m_options.m_cascade, m_options.m_match_type, m_options.m_category);
2233 
2234   for (auto &entry : command.entries()) {
2235     if (entry.ref().empty()) {
2236       result.AppendError("empty typenames not allowed");
2237       return false;
2238     }
2239 
2240     options->m_target_types << std::string(entry.ref());
2241   }
2242 
2243   m_interpreter.GetPythonCommandsFromIOHandler(
2244       "    ",             // Prompt
2245       *this,              // IOHandlerDelegate
2246       options.release()); // Baton for the "io_handler" that will be passed back
2247                           // into our IOHandlerDelegate functions
2248   result.SetStatus(eReturnStatusSuccessFinishNoResult);
2249   return result.Succeeded();
2250 }
2251 
2252 bool CommandObjectTypeSynthAdd::Execute_PythonClass(
2253     Args &command, CommandReturnObject &result) {
2254   const size_t argc = command.GetArgumentCount();
2255 
2256   if (argc < 1) {
2257     result.AppendErrorWithFormat("%s takes one or more args.\n",
2258                                  m_cmd_name.c_str());
2259     return false;
2260   }
2261 
2262   if (m_options.m_class_name.empty() && !m_options.m_input_python) {
2263     result.AppendErrorWithFormat("%s needs either a Python class name or -P to "
2264                                  "directly input Python code.\n",
2265                                  m_cmd_name.c_str());
2266     return false;
2267   }
2268 
2269   SyntheticChildrenSP entry;
2270 
2271   ScriptedSyntheticChildren *impl = new ScriptedSyntheticChildren(
2272       SyntheticChildren::Flags()
2273           .SetCascades(m_options.m_cascade)
2274           .SetSkipPointers(m_options.m_skip_pointers)
2275           .SetSkipReferences(m_options.m_skip_references),
2276       m_options.m_class_name.c_str());
2277 
2278   entry.reset(impl);
2279 
2280   ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
2281 
2282   if (interpreter &&
2283       !interpreter->CheckObjectExists(impl->GetPythonClassName()))
2284     result.AppendWarning("The provided class does not exist - please define it "
2285                          "before attempting to use this synthetic provider");
2286 
2287   // now I have a valid provider, let's add it to every type
2288 
2289   lldb::TypeCategoryImplSP category;
2290   DataVisualization::Categories::GetCategory(
2291       ConstString(m_options.m_category.c_str()), category);
2292 
2293   Status error;
2294 
2295   for (auto &arg_entry : command.entries()) {
2296     if (arg_entry.ref().empty()) {
2297       result.AppendError("empty typenames not allowed");
2298       return false;
2299     }
2300 
2301     ConstString typeCS(arg_entry.ref());
2302     if (!AddSynth(typeCS, entry, m_options.m_match_type, m_options.m_category,
2303                   &error)) {
2304       result.AppendError(error.AsCString());
2305       return false;
2306     }
2307   }
2308 
2309   result.SetStatus(eReturnStatusSuccessFinishNoResult);
2310   return result.Succeeded();
2311 }
2312 
2313 CommandObjectTypeSynthAdd::CommandObjectTypeSynthAdd(
2314     CommandInterpreter &interpreter)
2315     : CommandObjectParsed(interpreter, "type synthetic add",
2316                           "Add a new synthetic provider for a type.", nullptr),
2317       IOHandlerDelegateMultiline("DONE"), m_options() {
2318   CommandArgumentEntry type_arg;
2319   CommandArgumentData type_style_arg;
2320 
2321   type_style_arg.arg_type = eArgTypeName;
2322   type_style_arg.arg_repetition = eArgRepeatPlus;
2323 
2324   type_arg.push_back(type_style_arg);
2325 
2326   m_arguments.push_back(type_arg);
2327 }
2328 
2329 bool CommandObjectTypeSynthAdd::AddSynth(ConstString type_name,
2330                                          SyntheticChildrenSP entry,
2331                                          FormatterMatchType match_type,
2332                                          std::string category_name,
2333                                          Status *error) {
2334   lldb::TypeCategoryImplSP category;
2335   DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()),
2336                                              category);
2337 
2338   if (match_type == eFormatterMatchExact) {
2339     if (FixArrayTypeNameWithRegex(type_name))
2340       match_type = eFormatterMatchRegex;
2341   }
2342 
2343   // Only check for conflicting filters in the same category if `type_name` is
2344   // an actual type name. Matching a regex string against registered regexes
2345   // doesn't work.
2346   if (match_type == eFormatterMatchExact) {
2347     // It's not generally possible to get a type object here. For example, this
2348     // command can be run before loading any binaries. Do just a best-effort
2349     // name-based lookup here to try to prevent conflicts.
2350     FormattersMatchCandidate candidate_type(type_name, nullptr, TypeImpl(),
2351                                             FormattersMatchCandidate::Flags());
2352     if (category->AnyMatches(candidate_type, eFormatCategoryItemFilter,
2353                              false)) {
2354       if (error)
2355         error->SetErrorStringWithFormat("cannot add synthetic for type %s when "
2356                                         "filter is defined in same category!",
2357                                         type_name.AsCString());
2358       return false;
2359     }
2360   }
2361 
2362   if (match_type == eFormatterMatchRegex) {
2363     RegularExpression typeRX(type_name.GetStringRef());
2364     if (!typeRX.IsValid()) {
2365       if (error)
2366         error->SetErrorString(
2367             "regex format error (maybe this is not really a regex?)");
2368       return false;
2369     }
2370   }
2371 
2372   if (match_type == eFormatterMatchCallback) {
2373     const char *function_name = type_name.AsCString();
2374     ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
2375     if (interpreter && !interpreter->CheckObjectExists(function_name)) {
2376       error->SetErrorStringWithFormat(
2377           "The provided recognizer function \"%s\" does not exist - "
2378           "please define it before attempting to use this summary.\n",
2379           function_name);
2380       return false;
2381     }
2382   }
2383 
2384   category->AddTypeSynthetic(type_name.GetStringRef(), match_type, entry);
2385   return true;
2386 }
2387 
2388 #define LLDB_OPTIONS_type_filter_add
2389 #include "CommandOptions.inc"
2390 
2391 class CommandObjectTypeFilterAdd : public CommandObjectParsed {
2392 private:
2393   class CommandOptions : public Options {
2394     typedef std::vector<std::string> option_vector;
2395 
2396   public:
2397     CommandOptions() = default;
2398 
2399     ~CommandOptions() override = default;
2400 
2401     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2402                           ExecutionContext *execution_context) override {
2403       Status error;
2404       const int short_option = m_getopt_table[option_idx].val;
2405       bool success;
2406 
2407       switch (short_option) {
2408       case 'C':
2409         m_cascade = OptionArgParser::ToBoolean(option_arg, true, &success);
2410         if (!success)
2411           error.SetErrorStringWithFormat("invalid value for cascade: %s",
2412                                          option_arg.str().c_str());
2413         break;
2414       case 'c':
2415         m_expr_paths.push_back(std::string(option_arg));
2416         has_child_list = true;
2417         break;
2418       case 'p':
2419         m_skip_pointers = true;
2420         break;
2421       case 'r':
2422         m_skip_references = true;
2423         break;
2424       case 'w':
2425         m_category = std::string(option_arg);
2426         break;
2427       case 'x':
2428         m_regex = true;
2429         break;
2430       default:
2431         llvm_unreachable("Unimplemented option");
2432       }
2433 
2434       return error;
2435     }
2436 
2437     void OptionParsingStarting(ExecutionContext *execution_context) override {
2438       m_cascade = true;
2439       m_skip_pointers = false;
2440       m_skip_references = false;
2441       m_category = "default";
2442       m_expr_paths.clear();
2443       has_child_list = false;
2444       m_regex = false;
2445     }
2446 
2447     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2448       return llvm::ArrayRef(g_type_filter_add_options);
2449     }
2450 
2451     // Instance variables to hold the values for command options.
2452 
2453     bool m_cascade;
2454     bool m_skip_references;
2455     bool m_skip_pointers;
2456     bool m_input_python;
2457     option_vector m_expr_paths;
2458     std::string m_category;
2459     bool has_child_list;
2460     bool m_regex;
2461 
2462     typedef option_vector::iterator ExpressionPathsIterator;
2463   };
2464 
2465   CommandOptions m_options;
2466 
2467   Options *GetOptions() override { return &m_options; }
2468 
2469   enum FilterFormatType { eRegularFilter, eRegexFilter };
2470 
2471   bool AddFilter(ConstString type_name, TypeFilterImplSP entry,
2472                  FilterFormatType type, std::string category_name,
2473                  Status *error) {
2474     lldb::TypeCategoryImplSP category;
2475     DataVisualization::Categories::GetCategory(
2476         ConstString(category_name.c_str()), category);
2477 
2478     if (type == eRegularFilter) {
2479       if (FixArrayTypeNameWithRegex(type_name))
2480         type = eRegexFilter;
2481     }
2482 
2483     // Only check for conflicting synthetic child providers in the same category
2484     // if `type_name` is an actual type name. Matching a regex string against
2485     // registered regexes doesn't work.
2486     if (type == eRegularFilter) {
2487       // It's not generally possible to get a type object here. For example,
2488       // this command can be run before loading any binaries. Do just a
2489       // best-effort name-based lookup here to try to prevent conflicts.
2490       FormattersMatchCandidate candidate_type(
2491           type_name, nullptr, TypeImpl(), FormattersMatchCandidate::Flags());
2492       lldb::SyntheticChildrenSP entry;
2493       if (category->AnyMatches(candidate_type, eFormatCategoryItemSynth,
2494                                false)) {
2495         if (error)
2496           error->SetErrorStringWithFormat("cannot add filter for type %s when "
2497                                           "synthetic is defined in same "
2498                                           "category!",
2499                                           type_name.AsCString());
2500         return false;
2501       }
2502     }
2503 
2504     FormatterMatchType match_type = eFormatterMatchExact;
2505     if (type == eRegexFilter) {
2506       match_type = eFormatterMatchRegex;
2507       RegularExpression typeRX(type_name.GetStringRef());
2508       if (!typeRX.IsValid()) {
2509         if (error)
2510           error->SetErrorString(
2511               "regex format error (maybe this is not really a regex?)");
2512         return false;
2513       }
2514     }
2515     category->AddTypeFilter(type_name.GetStringRef(), match_type, entry);
2516     return true;
2517   }
2518 
2519 public:
2520   CommandObjectTypeFilterAdd(CommandInterpreter &interpreter)
2521       : CommandObjectParsed(interpreter, "type filter add",
2522                             "Add a new filter for a type.", nullptr) {
2523     CommandArgumentEntry type_arg;
2524     CommandArgumentData type_style_arg;
2525 
2526     type_style_arg.arg_type = eArgTypeName;
2527     type_style_arg.arg_repetition = eArgRepeatPlus;
2528 
2529     type_arg.push_back(type_style_arg);
2530 
2531     m_arguments.push_back(type_arg);
2532 
2533     SetHelpLong(
2534         R"(
2535 The following examples of 'type filter add' refer to this code snippet for context:
2536 
2537     class Foo {
2538         int a;
2539         int b;
2540         int c;
2541         int d;
2542         int e;
2543         int f;
2544         int g;
2545         int h;
2546         int i;
2547     }
2548     Foo my_foo;
2549 
2550 Adding a simple filter:
2551 
2552 (lldb) type filter add --child a --child g Foo
2553 (lldb) frame variable my_foo
2554 
2555 )"
2556         "Produces output where only a and g are displayed.  Other children of my_foo \
2557 (b, c, d, e, f, h and i) are available by asking for them explicitly:"
2558         R"(
2559 
2560 (lldb) frame variable my_foo.b my_foo.c my_foo.i
2561 
2562 )"
2563         "The formatting option --raw on frame variable bypasses the filter, showing \
2564 all children of my_foo as if no filter was defined:"
2565         R"(
2566 
2567 (lldb) frame variable my_foo --raw)");
2568   }
2569 
2570   ~CommandObjectTypeFilterAdd() override = default;
2571 
2572 protected:
2573   bool DoExecute(Args &command, CommandReturnObject &result) override {
2574     const size_t argc = command.GetArgumentCount();
2575 
2576     if (argc < 1) {
2577       result.AppendErrorWithFormat("%s takes one or more args.\n",
2578                                    m_cmd_name.c_str());
2579       return false;
2580     }
2581 
2582     if (m_options.m_expr_paths.empty()) {
2583       result.AppendErrorWithFormat("%s needs one or more children.\n",
2584                                    m_cmd_name.c_str());
2585       return false;
2586     }
2587 
2588     TypeFilterImplSP entry(new TypeFilterImpl(
2589         SyntheticChildren::Flags()
2590             .SetCascades(m_options.m_cascade)
2591             .SetSkipPointers(m_options.m_skip_pointers)
2592             .SetSkipReferences(m_options.m_skip_references)));
2593 
2594     // go through the expression paths
2595     CommandOptions::ExpressionPathsIterator begin,
2596         end = m_options.m_expr_paths.end();
2597 
2598     for (begin = m_options.m_expr_paths.begin(); begin != end; begin++)
2599       entry->AddExpressionPath(*begin);
2600 
2601     // now I have a valid provider, let's add it to every type
2602 
2603     lldb::TypeCategoryImplSP category;
2604     DataVisualization::Categories::GetCategory(
2605         ConstString(m_options.m_category.c_str()), category);
2606 
2607     Status error;
2608 
2609     WarnOnPotentialUnquotedUnsignedType(command, result);
2610 
2611     for (auto &arg_entry : command.entries()) {
2612       if (arg_entry.ref().empty()) {
2613         result.AppendError("empty typenames not allowed");
2614         return false;
2615       }
2616 
2617       ConstString typeCS(arg_entry.ref());
2618       if (!AddFilter(typeCS, entry,
2619                      m_options.m_regex ? eRegexFilter : eRegularFilter,
2620                      m_options.m_category, &error)) {
2621         result.AppendError(error.AsCString());
2622         return false;
2623       }
2624     }
2625 
2626     result.SetStatus(eReturnStatusSuccessFinishNoResult);
2627     return result.Succeeded();
2628   }
2629 };
2630 
2631 // "type lookup"
2632 #define LLDB_OPTIONS_type_lookup
2633 #include "CommandOptions.inc"
2634 
2635 class CommandObjectTypeLookup : public CommandObjectRaw {
2636 protected:
2637   // this function is allowed to do a more aggressive job at guessing languages
2638   // than the expression parser is comfortable with - so leave the original
2639   // call alone and add one that is specific to type lookup
2640   lldb::LanguageType GuessLanguage(StackFrame *frame) {
2641     lldb::LanguageType lang_type = lldb::eLanguageTypeUnknown;
2642 
2643     if (!frame)
2644       return lang_type;
2645 
2646     lang_type = frame->GuessLanguage();
2647     if (lang_type != lldb::eLanguageTypeUnknown)
2648       return lang_type;
2649 
2650     Symbol *s = frame->GetSymbolContext(eSymbolContextSymbol).symbol;
2651     if (s)
2652       lang_type = s->GetMangled().GuessLanguage();
2653 
2654     return lang_type;
2655   }
2656 
2657   class CommandOptions : public OptionGroup {
2658   public:
2659     CommandOptions() = default;
2660 
2661     ~CommandOptions() override = default;
2662 
2663     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2664       return llvm::ArrayRef(g_type_lookup_options);
2665     }
2666 
2667     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
2668                           ExecutionContext *execution_context) override {
2669       Status error;
2670 
2671       const int short_option = g_type_lookup_options[option_idx].short_option;
2672 
2673       switch (short_option) {
2674       case 'h':
2675         m_show_help = true;
2676         break;
2677 
2678       case 'l':
2679         m_language = Language::GetLanguageTypeFromString(option_value);
2680         break;
2681 
2682       default:
2683         llvm_unreachable("Unimplemented option");
2684       }
2685 
2686       return error;
2687     }
2688 
2689     void OptionParsingStarting(ExecutionContext *execution_context) override {
2690       m_show_help = false;
2691       m_language = eLanguageTypeUnknown;
2692     }
2693 
2694     // Options table: Required for subclasses of Options.
2695 
2696     bool m_show_help = false;
2697     lldb::LanguageType m_language = eLanguageTypeUnknown;
2698   };
2699 
2700   OptionGroupOptions m_option_group;
2701   CommandOptions m_command_options;
2702 
2703 public:
2704   CommandObjectTypeLookup(CommandInterpreter &interpreter)
2705       : CommandObjectRaw(interpreter, "type lookup",
2706                          "Lookup types and declarations in the current target, "
2707                          "following language-specific naming conventions.",
2708                          "type lookup <type-specifier>",
2709                          eCommandRequiresTarget) {
2710     m_option_group.Append(&m_command_options);
2711     m_option_group.Finalize();
2712   }
2713 
2714   ~CommandObjectTypeLookup() override = default;
2715 
2716   Options *GetOptions() override { return &m_option_group; }
2717 
2718   llvm::StringRef GetHelpLong() override {
2719     if (!m_cmd_help_long.empty())
2720       return m_cmd_help_long;
2721 
2722     StreamString stream;
2723     Language::ForEach([&](Language *lang) {
2724       if (const char *help = lang->GetLanguageSpecificTypeLookupHelp())
2725         stream.Printf("%s\n", help);
2726       return true;
2727     });
2728 
2729     m_cmd_help_long = std::string(stream.GetString());
2730     return m_cmd_help_long;
2731   }
2732 
2733   bool DoExecute(llvm::StringRef raw_command_line,
2734                  CommandReturnObject &result) override {
2735     if (raw_command_line.empty()) {
2736       result.AppendError(
2737           "type lookup cannot be invoked without a type name as argument");
2738       return false;
2739     }
2740 
2741     auto exe_ctx = GetCommandInterpreter().GetExecutionContext();
2742     m_option_group.NotifyOptionParsingStarting(&exe_ctx);
2743 
2744     OptionsWithRaw args(raw_command_line);
2745     const char *name_of_type = args.GetRawPart().c_str();
2746 
2747     if (args.HasArgs())
2748       if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group,
2749                                  exe_ctx))
2750         return false;
2751 
2752     ExecutionContextScope *best_scope = exe_ctx.GetBestExecutionContextScope();
2753 
2754     bool any_found = false;
2755 
2756     std::vector<Language *> languages;
2757 
2758     bool is_global_search = false;
2759     LanguageType guessed_language = lldb::eLanguageTypeUnknown;
2760 
2761     if ((is_global_search =
2762              (m_command_options.m_language == eLanguageTypeUnknown))) {
2763       Language::ForEach([&](Language *lang) {
2764         languages.push_back(lang);
2765         return true;
2766       });
2767     } else {
2768       languages.push_back(Language::FindPlugin(m_command_options.m_language));
2769     }
2770 
2771     // This is not the most efficient way to do this, but we support very few
2772     // languages so the cost of the sort is going to be dwarfed by the actual
2773     // lookup anyway
2774     if (StackFrame *frame = m_exe_ctx.GetFramePtr()) {
2775       guessed_language = GuessLanguage(frame);
2776       if (guessed_language != eLanguageTypeUnknown) {
2777         llvm::sort(
2778             languages.begin(), languages.end(),
2779             [guessed_language](Language *lang1, Language *lang2) -> bool {
2780               if (!lang1 || !lang2)
2781                 return false;
2782               LanguageType lt1 = lang1->GetLanguageType();
2783               LanguageType lt2 = lang2->GetLanguageType();
2784               if (lt1 == guessed_language)
2785                 return true; // make the selected frame's language come first
2786               if (lt2 == guessed_language)
2787                 return false; // make the selected frame's language come first
2788               return (lt1 < lt2); // normal comparison otherwise
2789             });
2790       }
2791     }
2792 
2793     bool is_first_language = true;
2794 
2795     for (Language *language : languages) {
2796       if (!language)
2797         continue;
2798 
2799       if (auto scavenger = language->GetTypeScavenger()) {
2800         Language::TypeScavenger::ResultSet search_results;
2801         if (scavenger->Find(best_scope, name_of_type, search_results) > 0) {
2802           for (const auto &search_result : search_results) {
2803             if (search_result && search_result->IsValid()) {
2804               any_found = true;
2805               search_result->DumpToStream(result.GetOutputStream(),
2806                                           this->m_command_options.m_show_help);
2807             }
2808           }
2809         }
2810       }
2811       // this is "type lookup SomeName" and we did find a match, so get out
2812       if (any_found && is_global_search)
2813         break;
2814       else if (is_first_language && is_global_search &&
2815                guessed_language != lldb::eLanguageTypeUnknown) {
2816         is_first_language = false;
2817         result.GetOutputStream().Printf(
2818             "no type was found in the current language %s matching '%s'; "
2819             "performing a global search across all languages\n",
2820             Language::GetNameForLanguageType(guessed_language), name_of_type);
2821       }
2822     }
2823 
2824     if (!any_found)
2825       result.AppendMessageWithFormat("no type was found matching '%s'\n",
2826                                      name_of_type);
2827 
2828     result.SetStatus(any_found ? lldb::eReturnStatusSuccessFinishResult
2829                                : lldb::eReturnStatusSuccessFinishNoResult);
2830     return true;
2831   }
2832 };
2833 
2834 template <typename FormatterType>
2835 class CommandObjectFormatterInfo : public CommandObjectRaw {
2836 public:
2837   typedef std::function<typename FormatterType::SharedPointer(ValueObject &)>
2838       DiscoveryFunction;
2839   CommandObjectFormatterInfo(CommandInterpreter &interpreter,
2840                              const char *formatter_name,
2841                              DiscoveryFunction discovery_func)
2842       : CommandObjectRaw(interpreter, "", "", "", eCommandRequiresFrame),
2843         m_formatter_name(formatter_name ? formatter_name : ""),
2844         m_discovery_function(discovery_func) {
2845     StreamString name;
2846     name.Printf("type %s info", formatter_name);
2847     SetCommandName(name.GetString());
2848     StreamString help;
2849     help.Printf("This command evaluates the provided expression and shows "
2850                 "which %s is applied to the resulting value (if any).",
2851                 formatter_name);
2852     SetHelp(help.GetString());
2853     StreamString syntax;
2854     syntax.Printf("type %s info <expr>", formatter_name);
2855     SetSyntax(syntax.GetString());
2856   }
2857 
2858   ~CommandObjectFormatterInfo() override = default;
2859 
2860 protected:
2861   bool DoExecute(llvm::StringRef command,
2862                  CommandReturnObject &result) override {
2863     TargetSP target_sp = GetDebugger().GetSelectedTarget();
2864     Thread *thread = GetDefaultThread();
2865     if (!thread) {
2866       result.AppendError("no default thread");
2867       return false;
2868     }
2869 
2870     StackFrameSP frame_sp =
2871         thread->GetSelectedFrame(DoNoSelectMostRelevantFrame);
2872     ValueObjectSP result_valobj_sp;
2873     EvaluateExpressionOptions options;
2874     lldb::ExpressionResults expr_result = target_sp->EvaluateExpression(
2875         command, frame_sp.get(), result_valobj_sp, options);
2876     if (expr_result == eExpressionCompleted && result_valobj_sp) {
2877       result_valobj_sp =
2878           result_valobj_sp->GetQualifiedRepresentationIfAvailable(
2879               target_sp->GetPreferDynamicValue(),
2880               target_sp->GetEnableSyntheticValue());
2881       typename FormatterType::SharedPointer formatter_sp =
2882           m_discovery_function(*result_valobj_sp);
2883       if (formatter_sp) {
2884         std::string description(formatter_sp->GetDescription());
2885         result.GetOutputStream()
2886             << m_formatter_name << " applied to ("
2887             << result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>")
2888             << ") " << command << " is: " << description << "\n";
2889         result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
2890       } else {
2891         result.GetOutputStream()
2892             << "no " << m_formatter_name << " applies to ("
2893             << result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>")
2894             << ") " << command << "\n";
2895         result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
2896       }
2897       return true;
2898     } else {
2899       result.AppendError("failed to evaluate expression");
2900       return false;
2901     }
2902   }
2903 
2904 private:
2905   std::string m_formatter_name;
2906   DiscoveryFunction m_discovery_function;
2907 };
2908 
2909 class CommandObjectTypeFormat : public CommandObjectMultiword {
2910 public:
2911   CommandObjectTypeFormat(CommandInterpreter &interpreter)
2912       : CommandObjectMultiword(
2913             interpreter, "type format",
2914             "Commands for customizing value display formats.",
2915             "type format [<sub-command-options>] ") {
2916     LoadSubCommand(
2917         "add", CommandObjectSP(new CommandObjectTypeFormatAdd(interpreter)));
2918     LoadSubCommand("clear", CommandObjectSP(
2919                                 new CommandObjectTypeFormatClear(interpreter)));
2920     LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFormatDelete(
2921                                  interpreter)));
2922     LoadSubCommand(
2923         "list", CommandObjectSP(new CommandObjectTypeFormatList(interpreter)));
2924     LoadSubCommand(
2925         "info", CommandObjectSP(new CommandObjectFormatterInfo<TypeFormatImpl>(
2926                     interpreter, "format",
2927                     [](ValueObject &valobj) -> TypeFormatImpl::SharedPointer {
2928                       return valobj.GetValueFormat();
2929                     })));
2930   }
2931 
2932   ~CommandObjectTypeFormat() override = default;
2933 };
2934 
2935 class CommandObjectTypeSynth : public CommandObjectMultiword {
2936 public:
2937   CommandObjectTypeSynth(CommandInterpreter &interpreter)
2938       : CommandObjectMultiword(
2939             interpreter, "type synthetic",
2940             "Commands for operating on synthetic type representations.",
2941             "type synthetic [<sub-command-options>] ") {
2942     LoadSubCommand("add",
2943                    CommandObjectSP(new CommandObjectTypeSynthAdd(interpreter)));
2944     LoadSubCommand(
2945         "clear", CommandObjectSP(new CommandObjectTypeSynthClear(interpreter)));
2946     LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSynthDelete(
2947                                  interpreter)));
2948     LoadSubCommand(
2949         "list", CommandObjectSP(new CommandObjectTypeSynthList(interpreter)));
2950     LoadSubCommand(
2951         "info",
2952         CommandObjectSP(new CommandObjectFormatterInfo<SyntheticChildren>(
2953             interpreter, "synthetic",
2954             [](ValueObject &valobj) -> SyntheticChildren::SharedPointer {
2955               return valobj.GetSyntheticChildren();
2956             })));
2957   }
2958 
2959   ~CommandObjectTypeSynth() override = default;
2960 };
2961 
2962 class CommandObjectTypeFilter : public CommandObjectMultiword {
2963 public:
2964   CommandObjectTypeFilter(CommandInterpreter &interpreter)
2965       : CommandObjectMultiword(interpreter, "type filter",
2966                                "Commands for operating on type filters.",
2967                                "type filter [<sub-command-options>] ") {
2968     LoadSubCommand(
2969         "add", CommandObjectSP(new CommandObjectTypeFilterAdd(interpreter)));
2970     LoadSubCommand("clear", CommandObjectSP(
2971                                 new CommandObjectTypeFilterClear(interpreter)));
2972     LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFilterDelete(
2973                                  interpreter)));
2974     LoadSubCommand(
2975         "list", CommandObjectSP(new CommandObjectTypeFilterList(interpreter)));
2976   }
2977 
2978   ~CommandObjectTypeFilter() override = default;
2979 };
2980 
2981 class CommandObjectTypeCategory : public CommandObjectMultiword {
2982 public:
2983   CommandObjectTypeCategory(CommandInterpreter &interpreter)
2984       : CommandObjectMultiword(interpreter, "type category",
2985                                "Commands for operating on type categories.",
2986                                "type category [<sub-command-options>] ") {
2987     LoadSubCommand(
2988         "define",
2989         CommandObjectSP(new CommandObjectTypeCategoryDefine(interpreter)));
2990     LoadSubCommand(
2991         "enable",
2992         CommandObjectSP(new CommandObjectTypeCategoryEnable(interpreter)));
2993     LoadSubCommand(
2994         "disable",
2995         CommandObjectSP(new CommandObjectTypeCategoryDisable(interpreter)));
2996     LoadSubCommand(
2997         "delete",
2998         CommandObjectSP(new CommandObjectTypeCategoryDelete(interpreter)));
2999     LoadSubCommand("list", CommandObjectSP(
3000                                new CommandObjectTypeCategoryList(interpreter)));
3001   }
3002 
3003   ~CommandObjectTypeCategory() override = default;
3004 };
3005 
3006 class CommandObjectTypeSummary : public CommandObjectMultiword {
3007 public:
3008   CommandObjectTypeSummary(CommandInterpreter &interpreter)
3009       : CommandObjectMultiword(
3010             interpreter, "type summary",
3011             "Commands for editing variable summary display options.",
3012             "type summary [<sub-command-options>] ") {
3013     LoadSubCommand(
3014         "add", CommandObjectSP(new CommandObjectTypeSummaryAdd(interpreter)));
3015     LoadSubCommand("clear", CommandObjectSP(new CommandObjectTypeSummaryClear(
3016                                 interpreter)));
3017     LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSummaryDelete(
3018                                  interpreter)));
3019     LoadSubCommand(
3020         "list", CommandObjectSP(new CommandObjectTypeSummaryList(interpreter)));
3021     LoadSubCommand(
3022         "info", CommandObjectSP(new CommandObjectFormatterInfo<TypeSummaryImpl>(
3023                     interpreter, "summary",
3024                     [](ValueObject &valobj) -> TypeSummaryImpl::SharedPointer {
3025                       return valobj.GetSummaryFormat();
3026                     })));
3027   }
3028 
3029   ~CommandObjectTypeSummary() override = default;
3030 };
3031 
3032 // CommandObjectType
3033 
3034 CommandObjectType::CommandObjectType(CommandInterpreter &interpreter)
3035     : CommandObjectMultiword(interpreter, "type",
3036                              "Commands for operating on the type system.",
3037                              "type [<sub-command-options>]") {
3038   LoadSubCommand("category",
3039                  CommandObjectSP(new CommandObjectTypeCategory(interpreter)));
3040   LoadSubCommand("filter",
3041                  CommandObjectSP(new CommandObjectTypeFilter(interpreter)));
3042   LoadSubCommand("format",
3043                  CommandObjectSP(new CommandObjectTypeFormat(interpreter)));
3044   LoadSubCommand("summary",
3045                  CommandObjectSP(new CommandObjectTypeSummary(interpreter)));
3046   LoadSubCommand("synthetic",
3047                  CommandObjectSP(new CommandObjectTypeSynth(interpreter)));
3048   LoadSubCommand("lookup",
3049                  CommandObjectSP(new CommandObjectTypeLookup(interpreter)));
3050 }
3051 
3052 CommandObjectType::~CommandObjectType() = default;
3053