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