//===-- CommandObjectType.cpp ---------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "CommandObjectType.h"

#include "lldb/Core/Debugger.h"
#include "lldb/Core/IOHandler.h"
#include "lldb/DataFormatters/DataVisualization.h"
#include "lldb/Host/Config.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/OptionGroupFormat.h"
#include "lldb/Interpreter/OptionValueBoolean.h"
#include "lldb/Interpreter/OptionValueLanguage.h"
#include "lldb/Interpreter/OptionValueString.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/Language.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/RegularExpression.h"
#include "lldb/Utility/StringList.h"

#include "llvm/ADT/STLExtras.h"

#include <algorithm>
#include <functional>
#include <memory>

#define CHECK_FORMATTER_KIND_MASK(VAL)                                         \
  ((m_formatter_kind_mask & (VAL)) == (VAL))

using namespace lldb;
using namespace lldb_private;

class ScriptAddOptions {
public:
  TypeSummaryImpl::Flags m_flags;
  StringList m_target_types;
  bool m_regex;
  ConstString m_name;
  std::string m_category;

  ScriptAddOptions(const TypeSummaryImpl::Flags &flags, bool regx,
                   ConstString name, std::string catg)
      : m_flags(flags), m_regex(regx), m_name(name), m_category(catg) {}

  typedef std::shared_ptr<ScriptAddOptions> SharedPointer;
};

class SynthAddOptions {
public:
  bool m_skip_pointers;
  bool m_skip_references;
  bool m_cascade;
  bool m_regex;
  StringList m_target_types;
  std::string m_category;

  SynthAddOptions(bool sptr, bool sref, bool casc, bool regx, std::string catg)
      : m_skip_pointers(sptr), m_skip_references(sref), m_cascade(casc),
        m_regex(regx), m_target_types(), m_category(catg) {}

  typedef std::shared_ptr<SynthAddOptions> SharedPointer;
};

static bool WarnOnPotentialUnquotedUnsignedType(Args &command,
                                                CommandReturnObject &result) {
  if (command.empty())
    return false;

  for (auto entry : llvm::enumerate(command.entries().drop_back())) {
    if (entry.value().ref() != "unsigned")
      continue;
    auto next = command.entries()[entry.index() + 1].ref();
    if (next == "int" || next == "short" || next == "char" || next == "long") {
      result.AppendWarningWithFormat(
          "unsigned %s being treated as two types. if you meant the combined "
          "type "
          "name use  quotes, as in \"unsigned %s\"\n",
          next.str().c_str(), next.str().c_str());
      return true;
    }
  }
  return false;
}

#define LLDB_OPTIONS_type_summary_add
#include "CommandOptions.inc"

class CommandObjectTypeSummaryAdd : public CommandObjectParsed,
                                    public IOHandlerDelegateMultiline {
private:
  class CommandOptions : public Options {
  public:
    CommandOptions(CommandInterpreter &interpreter) : Options() {}

    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override;

    void OptionParsingStarting(ExecutionContext *execution_context) override;

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::makeArrayRef(g_type_summary_add_options);
    }

    // Instance variables to hold the values for command options.

    TypeSummaryImpl::Flags m_flags;
    bool m_regex;
    std::string m_format_string;
    ConstString m_name;
    std::string m_python_script;
    std::string m_python_function;
    bool m_is_add_script;
    std::string m_category;
  };

  CommandOptions m_options;

  Options *GetOptions() override { return &m_options; }

  bool Execute_ScriptSummary(Args &command, CommandReturnObject &result);

  bool Execute_StringSummary(Args &command, CommandReturnObject &result);

public:
  enum SummaryFormatType { eRegularSummary, eRegexSummary, eNamedSummary };

  CommandObjectTypeSummaryAdd(CommandInterpreter &interpreter);

  ~CommandObjectTypeSummaryAdd() override = default;

  void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
    static const char *g_summary_addreader_instructions =
        "Enter your Python command(s). Type 'DONE' to end.\n"
        "def function (valobj,internal_dict):\n"
        "     \"\"\"valobj: an SBValue which you want to provide a summary "
        "for\n"
        "        internal_dict: an LLDB support object not to be used\"\"\"\n";

    StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
    if (output_sp && interactive) {
      output_sp->PutCString(g_summary_addreader_instructions);
      output_sp->Flush();
    }
  }

  void IOHandlerInputComplete(IOHandler &io_handler,
                              std::string &data) override {
    StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();

#if LLDB_ENABLE_PYTHON
    ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
    if (interpreter) {
      StringList lines;
      lines.SplitIntoLines(data);
      if (lines.GetSize() > 0) {
        ScriptAddOptions *options_ptr =
            ((ScriptAddOptions *)io_handler.GetUserData());
        if (options_ptr) {
          ScriptAddOptions::SharedPointer options(
              options_ptr); // this will ensure that we get rid of the pointer
                            // when going out of scope

          ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
          if (interpreter) {
            std::string funct_name_str;
            if (interpreter->GenerateTypeScriptFunction(lines,
                                                        funct_name_str)) {
              if (funct_name_str.empty()) {
                error_sp->Printf("unable to obtain a valid function name from "
                                 "the script interpreter.\n");
                error_sp->Flush();
              } else {
                // now I have a valid function name, let's add this as script
                // for every type in the list

                TypeSummaryImplSP script_format;
                script_format = std::make_shared<ScriptSummaryFormat>(
                    options->m_flags, funct_name_str.c_str(),
                    lines.CopyList("    ").c_str());

                Status error;

                for (const std::string &type_name : options->m_target_types) {
                  CommandObjectTypeSummaryAdd::AddSummary(
                      ConstString(type_name), script_format,
                      (options->m_regex
                           ? CommandObjectTypeSummaryAdd::eRegexSummary
                           : CommandObjectTypeSummaryAdd::eRegularSummary),
                      options->m_category, &error);
                  if (error.Fail()) {
                    error_sp->Printf("error: %s", error.AsCString());
                    error_sp->Flush();
                  }
                }

                if (options->m_name) {
                  CommandObjectTypeSummaryAdd::AddSummary(
                      options->m_name, script_format,
                      CommandObjectTypeSummaryAdd::eNamedSummary,
                      options->m_category, &error);
                  if (error.Fail()) {
                    CommandObjectTypeSummaryAdd::AddSummary(
                        options->m_name, script_format,
                        CommandObjectTypeSummaryAdd::eNamedSummary,
                        options->m_category, &error);
                    if (error.Fail()) {
                      error_sp->Printf("error: %s", error.AsCString());
                      error_sp->Flush();
                    }
                  } else {
                    error_sp->Printf("error: %s", error.AsCString());
                    error_sp->Flush();
                  }
                } else {
                  if (error.AsCString()) {
                    error_sp->Printf("error: %s", error.AsCString());
                    error_sp->Flush();
                  }
                }
              }
            } else {
              error_sp->Printf("error: unable to generate a function.\n");
              error_sp->Flush();
            }
          } else {
            error_sp->Printf("error: no script interpreter.\n");
            error_sp->Flush();
          }
        } else {
          error_sp->Printf("error: internal synchronization information "
                           "missing or invalid.\n");
          error_sp->Flush();
        }
      } else {
        error_sp->Printf("error: empty function, didn't add python command.\n");
        error_sp->Flush();
      }
    } else {
      error_sp->Printf(
          "error: script interpreter missing, didn't add python command.\n");
      error_sp->Flush();
    }
#endif
    io_handler.SetIsDone(true);
  }

  static bool AddSummary(ConstString type_name, lldb::TypeSummaryImplSP entry,
                         SummaryFormatType type, std::string category,
                         Status *error = nullptr);

protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override;
};

static const char *g_synth_addreader_instructions =
    "Enter your Python command(s). Type 'DONE' to end.\n"
    "You must define a Python class with these methods:\n"
    "    def __init__(self, valobj, internal_dict):\n"
    "    def num_children(self):\n"
    "    def get_child_at_index(self, index):\n"
    "    def get_child_index(self, name):\n"
    "    def update(self):\n"
    "        '''Optional'''\n"
    "class synthProvider:\n";

#define LLDB_OPTIONS_type_synth_add
#include "CommandOptions.inc"

class CommandObjectTypeSynthAdd : public CommandObjectParsed,
                                  public IOHandlerDelegateMultiline {
private:
  class CommandOptions : public Options {
  public:
    CommandOptions() : Options() {}

    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      Status error;
      const int short_option = m_getopt_table[option_idx].val;
      bool success;

      switch (short_option) {
      case 'C':
        m_cascade = OptionArgParser::ToBoolean(option_arg, true, &success);
        if (!success)
          error.SetErrorStringWithFormat("invalid value for cascade: %s",
                                         option_arg.str().c_str());
        break;
      case 'P':
        handwrite_python = true;
        break;
      case 'l':
        m_class_name = std::string(option_arg);
        is_class_based = true;
        break;
      case 'p':
        m_skip_pointers = true;
        break;
      case 'r':
        m_skip_references = true;
        break;
      case 'w':
        m_category = std::string(option_arg);
        break;
      case 'x':
        m_regex = true;
        break;
      default:
        llvm_unreachable("Unimplemented option");
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_cascade = true;
      m_class_name = "";
      m_skip_pointers = false;
      m_skip_references = false;
      m_category = "default";
      is_class_based = false;
      handwrite_python = false;
      m_regex = false;
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::makeArrayRef(g_type_synth_add_options);
    }

    // Instance variables to hold the values for command options.

    bool m_cascade;
    bool m_skip_references;
    bool m_skip_pointers;
    std::string m_class_name;
    bool m_input_python;
    std::string m_category;
    bool is_class_based;
    bool handwrite_python;
    bool m_regex;
  };

  CommandOptions m_options;

  Options *GetOptions() override { return &m_options; }

  bool Execute_HandwritePython(Args &command, CommandReturnObject &result);

  bool Execute_PythonClass(Args &command, CommandReturnObject &result);

protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    WarnOnPotentialUnquotedUnsignedType(command, result);

    if (m_options.handwrite_python)
      return Execute_HandwritePython(command, result);
    else if (m_options.is_class_based)
      return Execute_PythonClass(command, result);
    else {
      result.AppendError("must either provide a children list, a Python class "
                         "name, or use -P and type a Python class "
                         "line-by-line");
      result.SetStatus(eReturnStatusFailed);
      return false;
    }
  }

  void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
    StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
    if (output_sp && interactive) {
      output_sp->PutCString(g_synth_addreader_instructions);
      output_sp->Flush();
    }
  }

  void IOHandlerInputComplete(IOHandler &io_handler,
                              std::string &data) override {
    StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();

#if LLDB_ENABLE_PYTHON
    ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
    if (interpreter) {
      StringList lines;
      lines.SplitIntoLines(data);
      if (lines.GetSize() > 0) {
        SynthAddOptions *options_ptr =
            ((SynthAddOptions *)io_handler.GetUserData());
        if (options_ptr) {
          SynthAddOptions::SharedPointer options(
              options_ptr); // this will ensure that we get rid of the pointer
                            // when going out of scope

          ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
          if (interpreter) {
            std::string class_name_str;
            if (interpreter->GenerateTypeSynthClass(lines, class_name_str)) {
              if (class_name_str.empty()) {
                error_sp->Printf(
                    "error: unable to obtain a proper name for the class.\n");
                error_sp->Flush();
              } else {
                // everything should be fine now, let's add the synth provider
                // class

                SyntheticChildrenSP synth_provider;
                synth_provider = std::make_shared<ScriptedSyntheticChildren>(
                    SyntheticChildren::Flags()
                        .SetCascades(options->m_cascade)
                        .SetSkipPointers(options->m_skip_pointers)
                        .SetSkipReferences(options->m_skip_references),
                    class_name_str.c_str());

                lldb::TypeCategoryImplSP category;
                DataVisualization::Categories::GetCategory(
                    ConstString(options->m_category.c_str()), category);

                Status error;

                for (const std::string &type_name : options->m_target_types) {
                  if (!type_name.empty()) {
                    if (!CommandObjectTypeSynthAdd::AddSynth(
                            ConstString(type_name), synth_provider,
                            options->m_regex
                                ? CommandObjectTypeSynthAdd::eRegexSynth
                                : CommandObjectTypeSynthAdd::eRegularSynth,
                            options->m_category, &error)) {
                      error_sp->Printf("error: %s\n", error.AsCString());
                      error_sp->Flush();
                      break;
                    }
                  } else {
                    error_sp->Printf("error: invalid type name.\n");
                    error_sp->Flush();
                    break;
                  }
                }
              }
            } else {
              error_sp->Printf("error: unable to generate a class.\n");
              error_sp->Flush();
            }
          } else {
            error_sp->Printf("error: no script interpreter.\n");
            error_sp->Flush();
          }
        } else {
          error_sp->Printf("error: internal synchronization data missing.\n");
          error_sp->Flush();
        }
      } else {
        error_sp->Printf("error: empty function, didn't add python command.\n");
        error_sp->Flush();
      }
    } else {
      error_sp->Printf(
          "error: script interpreter missing, didn't add python command.\n");
      error_sp->Flush();
    }

#endif
    io_handler.SetIsDone(true);
  }

public:
  enum SynthFormatType { eRegularSynth, eRegexSynth };

  CommandObjectTypeSynthAdd(CommandInterpreter &interpreter);

  ~CommandObjectTypeSynthAdd() override = default;

  static bool AddSynth(ConstString type_name, lldb::SyntheticChildrenSP entry,
                       SynthFormatType type, std::string category_name,
                       Status *error);
};

// CommandObjectTypeFormatAdd

#define LLDB_OPTIONS_type_format_add
#include "CommandOptions.inc"

class CommandObjectTypeFormatAdd : public CommandObjectParsed {
private:
  class CommandOptions : public OptionGroup {
  public:
    CommandOptions() : OptionGroup() {}

    ~CommandOptions() override = default;

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::makeArrayRef(g_type_format_add_options);
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_cascade = true;
      m_skip_pointers = false;
      m_skip_references = false;
      m_regex = false;
      m_category.assign("default");
      m_custom_type_name.clear();
    }

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
                          ExecutionContext *execution_context) override {
      Status error;
      const int short_option =
          g_type_format_add_options[option_idx].short_option;
      bool success;

      switch (short_option) {
      case 'C':
        m_cascade = OptionArgParser::ToBoolean(option_value, true, &success);
        if (!success)
          error.SetErrorStringWithFormat("invalid value for cascade: %s",
                                         option_value.str().c_str());
        break;
      case 'p':
        m_skip_pointers = true;
        break;
      case 'w':
        m_category.assign(std::string(option_value));
        break;
      case 'r':
        m_skip_references = true;
        break;
      case 'x':
        m_regex = true;
        break;
      case 't':
        m_custom_type_name.assign(std::string(option_value));
        break;
      default:
        llvm_unreachable("Unimplemented option");
      }

      return error;
    }

    // Instance variables to hold the values for command options.

    bool m_cascade;
    bool m_skip_references;
    bool m_skip_pointers;
    bool m_regex;
    std::string m_category;
    std::string m_custom_type_name;
  };

  OptionGroupOptions m_option_group;
  OptionGroupFormat m_format_options;
  CommandOptions m_command_options;

  Options *GetOptions() override { return &m_option_group; }

public:
  CommandObjectTypeFormatAdd(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "type format add",
                            "Add a new formatting style for a type.", nullptr),
        m_option_group(), m_format_options(eFormatInvalid),
        m_command_options() {
    CommandArgumentEntry type_arg;
    CommandArgumentData type_style_arg;

    type_style_arg.arg_type = eArgTypeName;
    type_style_arg.arg_repetition = eArgRepeatPlus;

    type_arg.push_back(type_style_arg);

    m_arguments.push_back(type_arg);

    SetHelpLong(
        R"(
The following examples of 'type format add' refer to this code snippet for context:

    typedef int Aint;
    typedef float Afloat;
    typedef Aint Bint;
    typedef Afloat Bfloat;

    Aint ix = 5;
    Bint iy = 5;

    Afloat fx = 3.14;
    BFloat fy = 3.14;

Adding default formatting:

(lldb) type format add -f hex AInt
(lldb) frame variable iy

)"
        "    Produces hexadecimal display of iy, because no formatter is available for Bint and \
the one for Aint is used instead."
        R"(

To prevent this use the cascade option '-C no' to prevent evaluation of typedef chains:


(lldb) type format add -f hex -C no AInt

Similar reasoning applies to this:

(lldb) type format add -f hex -C no float -p

)"
        "    All float values and float references are now formatted as hexadecimal, but not \
pointers to floats.  Nor will it change the default display for Afloat and Bfloat objects.");

    // Add the "--format" to all options groups
    m_option_group.Append(&m_format_options,
                          OptionGroupFormat::OPTION_GROUP_FORMAT,
                          LLDB_OPT_SET_1);
    m_option_group.Append(&m_command_options);
    m_option_group.Finalize();
  }

  ~CommandObjectTypeFormatAdd() override = default;

protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    const size_t argc = command.GetArgumentCount();

    if (argc < 1) {
      result.AppendErrorWithFormat("%s takes one or more args.\n",
                                   m_cmd_name.c_str());
      result.SetStatus(eReturnStatusFailed);
      return false;
    }

    const Format format = m_format_options.GetFormat();
    if (format == eFormatInvalid &&
        m_command_options.m_custom_type_name.empty()) {
      result.AppendErrorWithFormat("%s needs a valid format.\n",
                                   m_cmd_name.c_str());
      result.SetStatus(eReturnStatusFailed);
      return false;
    }

    TypeFormatImplSP entry;

    if (m_command_options.m_custom_type_name.empty())
      entry = std::make_shared<TypeFormatImpl_Format>(
          format, TypeFormatImpl::Flags()
                      .SetCascades(m_command_options.m_cascade)
                      .SetSkipPointers(m_command_options.m_skip_pointers)
                      .SetSkipReferences(m_command_options.m_skip_references));
    else
      entry = std::make_shared<TypeFormatImpl_EnumType>(
          ConstString(m_command_options.m_custom_type_name.c_str()),
          TypeFormatImpl::Flags()
              .SetCascades(m_command_options.m_cascade)
              .SetSkipPointers(m_command_options.m_skip_pointers)
              .SetSkipReferences(m_command_options.m_skip_references));

    // now I have a valid format, let's add it to every type

    TypeCategoryImplSP category_sp;
    DataVisualization::Categories::GetCategory(
        ConstString(m_command_options.m_category), category_sp);
    if (!category_sp)
      return false;

    WarnOnPotentialUnquotedUnsignedType(command, result);

    for (auto &arg_entry : command.entries()) {
      if (arg_entry.ref().empty()) {
        result.AppendError("empty typenames not allowed");
        result.SetStatus(eReturnStatusFailed);
        return false;
      }

      ConstString typeCS(arg_entry.ref());
      if (m_command_options.m_regex) {
        RegularExpression typeRX(arg_entry.ref());
        if (!typeRX.IsValid()) {
          result.AppendError(
              "regex format error (maybe this is not really a regex?)");
          result.SetStatus(eReturnStatusFailed);
          return false;
        }
        category_sp->GetRegexTypeSummariesContainer()->Delete(typeCS);
        category_sp->GetRegexTypeFormatsContainer()->Add(std::move(typeRX),
                                                         entry);
      } else
        category_sp->GetTypeFormatsContainer()->Add(std::move(typeCS), entry);
    }

    result.SetStatus(eReturnStatusSuccessFinishNoResult);
    return result.Succeeded();
  }
};

#define LLDB_OPTIONS_type_formatter_delete
#include "CommandOptions.inc"

class CommandObjectTypeFormatterDelete : public CommandObjectParsed {
protected:
  class CommandOptions : public Options {
  public:
    CommandOptions() : Options() {}

    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      Status error;
      const int short_option = m_getopt_table[option_idx].val;

      switch (short_option) {
      case 'a':
        m_delete_all = true;
        break;
      case 'w':
        m_category = std::string(option_arg);
        break;
      case 'l':
        m_language = Language::GetLanguageTypeFromString(option_arg);
        break;
      default:
        llvm_unreachable("Unimplemented option");
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_delete_all = false;
      m_category = "default";
      m_language = lldb::eLanguageTypeUnknown;
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::makeArrayRef(g_type_formatter_delete_options);
    }

    // Instance variables to hold the values for command options.

    bool m_delete_all;
    std::string m_category;
    lldb::LanguageType m_language;
  };

  CommandOptions m_options;
  uint32_t m_formatter_kind_mask;

  Options *GetOptions() override { return &m_options; }

public:
  CommandObjectTypeFormatterDelete(CommandInterpreter &interpreter,
                                   uint32_t formatter_kind_mask,
                                   const char *name, const char *help)
      : CommandObjectParsed(interpreter, name, help, nullptr), m_options(),
        m_formatter_kind_mask(formatter_kind_mask) {
    CommandArgumentEntry type_arg;
    CommandArgumentData type_style_arg;

    type_style_arg.arg_type = eArgTypeName;
    type_style_arg.arg_repetition = eArgRepeatPlain;

    type_arg.push_back(type_style_arg);

    m_arguments.push_back(type_arg);
  }

  ~CommandObjectTypeFormatterDelete() override = default;

  void
  HandleArgumentCompletion(CompletionRequest &request,
                           OptionElementVector &opt_element_vector) override {
    if (request.GetCursorIndex())
      return;

    DataVisualization::Categories::ForEach(
        [this, &request](const lldb::TypeCategoryImplSP &category_sp) {
          if (CHECK_FORMATTER_KIND_MASK(eFormatCategoryItemValue))
            category_sp->GetTypeFormatsContainer()->AutoComplete(request);
          if (CHECK_FORMATTER_KIND_MASK(eFormatCategoryItemRegexValue))
            category_sp->GetRegexTypeFormatsContainer()->AutoComplete(request);

          if (CHECK_FORMATTER_KIND_MASK(eFormatCategoryItemSummary))
            category_sp->GetTypeSummariesContainer()->AutoComplete(request);
          if (CHECK_FORMATTER_KIND_MASK(eFormatCategoryItemRegexSummary))
            category_sp->GetRegexTypeSummariesContainer()->AutoComplete(
                request);

          if (CHECK_FORMATTER_KIND_MASK(eFormatCategoryItemFilter))
            category_sp->GetTypeFiltersContainer()->AutoComplete(request);
          if (CHECK_FORMATTER_KIND_MASK(eFormatCategoryItemRegexFilter))
            category_sp->GetRegexTypeFiltersContainer()->AutoComplete(request);

          if (CHECK_FORMATTER_KIND_MASK(eFormatCategoryItemSynth))
            category_sp->GetTypeSyntheticsContainer()->AutoComplete(request);
          if (CHECK_FORMATTER_KIND_MASK(eFormatCategoryItemRegexSynth))
            category_sp->GetRegexTypeSyntheticsContainer()->AutoComplete(
                request);
          return true;
        });
  }

protected:
  virtual bool FormatterSpecificDeletion(ConstString typeCS) { return false; }

  bool DoExecute(Args &command, CommandReturnObject &result) override {
    const size_t argc = command.GetArgumentCount();

    if (argc != 1) {
      result.AppendErrorWithFormat("%s takes 1 arg.\n", m_cmd_name.c_str());
      result.SetStatus(eReturnStatusFailed);
      return false;
    }

    const char *typeA = command.GetArgumentAtIndex(0);
    ConstString typeCS(typeA);

    if (!typeCS) {
      result.AppendError("empty typenames not allowed");
      result.SetStatus(eReturnStatusFailed);
      return false;
    }

    if (m_options.m_delete_all) {
      DataVisualization::Categories::ForEach(
          [this, typeCS](const lldb::TypeCategoryImplSP &category_sp) -> bool {
            category_sp->Delete(typeCS, m_formatter_kind_mask);
            return true;
          });
      result.SetStatus(eReturnStatusSuccessFinishNoResult);
      return result.Succeeded();
    }

    bool delete_category = false;
    bool extra_deletion = false;

    if (m_options.m_language != lldb::eLanguageTypeUnknown) {
      lldb::TypeCategoryImplSP category;
      DataVisualization::Categories::GetCategory(m_options.m_language,
                                                 category);
      if (category)
        delete_category = category->Delete(typeCS, m_formatter_kind_mask);
      extra_deletion = FormatterSpecificDeletion(typeCS);
    } else {
      lldb::TypeCategoryImplSP category;
      DataVisualization::Categories::GetCategory(
          ConstString(m_options.m_category.c_str()), category);
      if (category)
        delete_category = category->Delete(typeCS, m_formatter_kind_mask);
      extra_deletion = FormatterSpecificDeletion(typeCS);
    }

    if (delete_category || extra_deletion) {
      result.SetStatus(eReturnStatusSuccessFinishNoResult);
      return result.Succeeded();
    } else {
      result.AppendErrorWithFormat("no custom formatter for %s.\n", typeA);
      result.SetStatus(eReturnStatusFailed);
      return false;
    }
  }
};

#define LLDB_OPTIONS_type_formatter_clear
#include "CommandOptions.inc"

class CommandObjectTypeFormatterClear : public CommandObjectParsed {
private:
  class CommandOptions : public Options {
  public:
    CommandOptions() : Options() {}

    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      Status error;
      const int short_option = m_getopt_table[option_idx].val;

      switch (short_option) {
      case 'a':
        m_delete_all = true;
        break;
      default:
        llvm_unreachable("Unimplemented option");
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_delete_all = false;
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::makeArrayRef(g_type_formatter_clear_options);
    }

    // Instance variables to hold the values for command options.
    bool m_delete_all;
  };

  CommandOptions m_options;
  uint32_t m_formatter_kind_mask;

  Options *GetOptions() override { return &m_options; }

public:
  CommandObjectTypeFormatterClear(CommandInterpreter &interpreter,
                                  uint32_t formatter_kind_mask,
                                  const char *name, const char *help)
      : CommandObjectParsed(interpreter, name, help, nullptr), m_options(),
        m_formatter_kind_mask(formatter_kind_mask) {}

  ~CommandObjectTypeFormatterClear() override = default;

protected:
  virtual void FormatterSpecificDeletion() {}

  bool DoExecute(Args &command, CommandReturnObject &result) override {
    if (m_options.m_delete_all) {
      DataVisualization::Categories::ForEach(
          [this](const TypeCategoryImplSP &category_sp) -> bool {
            category_sp->Clear(m_formatter_kind_mask);
            return true;
          });
    } else {
      lldb::TypeCategoryImplSP category;
      if (command.GetArgumentCount() > 0) {
        const char *cat_name = command.GetArgumentAtIndex(0);
        ConstString cat_nameCS(cat_name);
        DataVisualization::Categories::GetCategory(cat_nameCS, category);
      } else {
        DataVisualization::Categories::GetCategory(ConstString(nullptr),
                                                   category);
      }
      category->Clear(m_formatter_kind_mask);
    }

    FormatterSpecificDeletion();

    result.SetStatus(eReturnStatusSuccessFinishResult);
    return result.Succeeded();
  }
};

// CommandObjectTypeFormatDelete

class CommandObjectTypeFormatDelete : public CommandObjectTypeFormatterDelete {
public:
  CommandObjectTypeFormatDelete(CommandInterpreter &interpreter)
      : CommandObjectTypeFormatterDelete(
            interpreter,
            eFormatCategoryItemValue | eFormatCategoryItemRegexValue,
            "type format delete",
            "Delete an existing formatting style for a type.") {}

  ~CommandObjectTypeFormatDelete() override = default;
};

// CommandObjectTypeFormatClear

class CommandObjectTypeFormatClear : public CommandObjectTypeFormatterClear {
public:
  CommandObjectTypeFormatClear(CommandInterpreter &interpreter)
      : CommandObjectTypeFormatterClear(
            interpreter,
            eFormatCategoryItemValue | eFormatCategoryItemRegexValue,
            "type format clear", "Delete all existing format styles.") {}
};

#define LLDB_OPTIONS_type_formatter_list
#include "CommandOptions.inc"

template <typename FormatterType>
class CommandObjectTypeFormatterList : public CommandObjectParsed {
  typedef typename FormatterType::SharedPointer FormatterSharedPointer;

  class CommandOptions : public Options {
  public:
    CommandOptions()
        : Options(), m_category_regex("", ""),
          m_category_language(lldb::eLanguageTypeUnknown,
                              lldb::eLanguageTypeUnknown) {}

    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      Status error;
      const int short_option = m_getopt_table[option_idx].val;
      switch (short_option) {
      case 'w':
        m_category_regex.SetCurrentValue(option_arg);
        m_category_regex.SetOptionWasSet();
        break;
      case 'l':
        error = m_category_language.SetValueFromString(option_arg);
        if (error.Success())
          m_category_language.SetOptionWasSet();
        break;
      default:
        llvm_unreachable("Unimplemented option");
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_category_regex.Clear();
      m_category_language.Clear();
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::makeArrayRef(g_type_formatter_list_options);
    }

    // Instance variables to hold the values for command options.

    OptionValueString m_category_regex;
    OptionValueLanguage m_category_language;
  };

  CommandOptions m_options;

  Options *GetOptions() override { return &m_options; }

public:
  CommandObjectTypeFormatterList(CommandInterpreter &interpreter,
                                 const char *name, const char *help)
      : CommandObjectParsed(interpreter, name, help, nullptr), m_options() {
    CommandArgumentEntry type_arg;
    CommandArgumentData type_style_arg;

    type_style_arg.arg_type = eArgTypeName;
    type_style_arg.arg_repetition = eArgRepeatOptional;

    type_arg.push_back(type_style_arg);

    m_arguments.push_back(type_arg);
  }

  ~CommandObjectTypeFormatterList() override = default;

protected:
  virtual bool FormatterSpecificList(CommandReturnObject &result) {
    return false;
  }

  bool DoExecute(Args &command, CommandReturnObject &result) override {
    const size_t argc = command.GetArgumentCount();

    std::unique_ptr<RegularExpression> category_regex;
    std::unique_ptr<RegularExpression> formatter_regex;

    if (m_options.m_category_regex.OptionWasSet()) {
      category_regex = std::make_unique<RegularExpression>(
          m_options.m_category_regex.GetCurrentValueAsRef());
      if (!category_regex->IsValid()) {
        result.AppendErrorWithFormat(
            "syntax error in category regular expression '%s'",
            m_options.m_category_regex.GetCurrentValueAsRef().str().c_str());
        result.SetStatus(eReturnStatusFailed);
        return false;
      }
    }

    if (argc == 1) {
      const char *arg = command.GetArgumentAtIndex(0);
      formatter_regex = std::make_unique<RegularExpression>(
          llvm::StringRef::withNullAsEmpty(arg));
      if (!formatter_regex->IsValid()) {
        result.AppendErrorWithFormat("syntax error in regular expression '%s'",
                                     arg);
        result.SetStatus(eReturnStatusFailed);
        return false;
      }
    }

    bool any_printed = false;

    auto category_closure =
        [&result, &formatter_regex,
         &any_printed](const lldb::TypeCategoryImplSP &category) -> void {
      result.GetOutputStream().Printf(
          "-----------------------\nCategory: %s%s\n-----------------------\n",
          category->GetName(), category->IsEnabled() ? "" : " (disabled)");

      TypeCategoryImpl::ForEachCallbacks<FormatterType> foreach;
      foreach
        .SetExact([&result, &formatter_regex, &any_printed](
                      const TypeMatcher &type_matcher,
                      const FormatterSharedPointer &format_sp) -> bool {
          if (formatter_regex) {
            bool escape = true;
            if (type_matcher.CreatedBySameMatchString(
                    ConstString(formatter_regex->GetText()))) {
              escape = false;
            } else if (formatter_regex->Execute(
                           type_matcher.GetMatchString().GetStringRef())) {
              escape = false;
            }

            if (escape)
              return true;
          }

          any_printed = true;
          result.GetOutputStream().Printf(
              "%s: %s\n", type_matcher.GetMatchString().GetCString(),
              format_sp->GetDescription().c_str());
          return true;
        });

      foreach
        .SetWithRegex([&result, &formatter_regex, &any_printed](
                          const TypeMatcher &type_matcher,
                          const FormatterSharedPointer &format_sp) -> bool {
          if (formatter_regex) {
            bool escape = true;
            if (type_matcher.CreatedBySameMatchString(
                    ConstString(formatter_regex->GetText()))) {
              escape = false;
            } else if (formatter_regex->Execute(
                           type_matcher.GetMatchString().GetStringRef())) {
              escape = false;
            }

            if (escape)
              return true;
          }

          any_printed = true;
          result.GetOutputStream().Printf(
              "%s: %s\n", type_matcher.GetMatchString().GetCString(),
              format_sp->GetDescription().c_str());
          return true;
        });

      category->ForEach(foreach);
    };

    if (m_options.m_category_language.OptionWasSet()) {
      lldb::TypeCategoryImplSP category_sp;
      DataVisualization::Categories::GetCategory(
          m_options.m_category_language.GetCurrentValue(), category_sp);
      if (category_sp)
        category_closure(category_sp);
    } else {
      DataVisualization::Categories::ForEach(
          [&category_regex, &category_closure](
              const lldb::TypeCategoryImplSP &category) -> bool {
            if (category_regex) {
              bool escape = true;
              if (category->GetName() == category_regex->GetText()) {
                escape = false;
              } else if (category_regex->Execute(
                             llvm::StringRef::withNullAsEmpty(
                                 category->GetName()))) {
                escape = false;
              }

              if (escape)
                return true;
            }

            category_closure(category);

            return true;
          });

      any_printed = FormatterSpecificList(result) | any_printed;
    }

    if (any_printed)
      result.SetStatus(eReturnStatusSuccessFinishResult);
    else {
      result.GetOutputStream().PutCString("no matching results found.\n");
      result.SetStatus(eReturnStatusSuccessFinishNoResult);
    }
    return result.Succeeded();
  }
};

// CommandObjectTypeFormatList

class CommandObjectTypeFormatList
    : public CommandObjectTypeFormatterList<TypeFormatImpl> {
public:
  CommandObjectTypeFormatList(CommandInterpreter &interpreter)
      : CommandObjectTypeFormatterList(interpreter, "type format list",
                                       "Show a list of current formats.") {}
};

Status CommandObjectTypeSummaryAdd::CommandOptions::SetOptionValue(
    uint32_t option_idx, llvm::StringRef option_arg,
    ExecutionContext *execution_context) {
  Status error;
  const int short_option = m_getopt_table[option_idx].val;
  bool success;

  switch (short_option) {
  case 'C':
    m_flags.SetCascades(OptionArgParser::ToBoolean(option_arg, true, &success));
    if (!success)
      error.SetErrorStringWithFormat("invalid value for cascade: %s",
                                     option_arg.str().c_str());
    break;
  case 'e':
    m_flags.SetDontShowChildren(false);
    break;
  case 'h':
    m_flags.SetHideEmptyAggregates(true);
    break;
  case 'v':
    m_flags.SetDontShowValue(true);
    break;
  case 'c':
    m_flags.SetShowMembersOneLiner(true);
    break;
  case 's':
    m_format_string = std::string(option_arg);
    break;
  case 'p':
    m_flags.SetSkipPointers(true);
    break;
  case 'r':
    m_flags.SetSkipReferences(true);
    break;
  case 'x':
    m_regex = true;
    break;
  case 'n':
    m_name.SetString(option_arg);
    break;
  case 'o':
    m_python_script = std::string(option_arg);
    m_is_add_script = true;
    break;
  case 'F':
    m_python_function = std::string(option_arg);
    m_is_add_script = true;
    break;
  case 'P':
    m_is_add_script = true;
    break;
  case 'w':
    m_category = std::string(option_arg);
    break;
  case 'O':
    m_flags.SetHideItemNames(true);
    break;
  default:
    llvm_unreachable("Unimplemented option");
  }

  return error;
}

void CommandObjectTypeSummaryAdd::CommandOptions::OptionParsingStarting(
    ExecutionContext *execution_context) {
  m_flags.Clear().SetCascades().SetDontShowChildren().SetDontShowValue(false);
  m_flags.SetShowMembersOneLiner(false)
      .SetSkipPointers(false)
      .SetSkipReferences(false)
      .SetHideItemNames(false);

  m_regex = false;
  m_name.Clear();
  m_python_script = "";
  m_python_function = "";
  m_format_string = "";
  m_is_add_script = false;
  m_category = "default";
}

#if LLDB_ENABLE_PYTHON

bool CommandObjectTypeSummaryAdd::Execute_ScriptSummary(
    Args &command, CommandReturnObject &result) {
  const size_t argc = command.GetArgumentCount();

  if (argc < 1 && !m_options.m_name) {
    result.AppendErrorWithFormat("%s takes one or more args.\n",
                                 m_cmd_name.c_str());
    result.SetStatus(eReturnStatusFailed);
    return false;
  }

  TypeSummaryImplSP script_format;

  if (!m_options.m_python_function
           .empty()) // we have a Python function ready to use
  {
    const char *funct_name = m_options.m_python_function.c_str();
    if (!funct_name || !funct_name[0]) {
      result.AppendError("function name empty.\n");
      result.SetStatus(eReturnStatusFailed);
      return false;
    }

    std::string code =
        ("    " + m_options.m_python_function + "(valobj,internal_dict)");

    script_format = std::make_shared<ScriptSummaryFormat>(
        m_options.m_flags, funct_name, code.c_str());

    ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();

    if (interpreter && !interpreter->CheckObjectExists(funct_name))
      result.AppendWarningWithFormat(
          "The provided function \"%s\" does not exist - "
          "please define it before attempting to use this summary.\n",
          funct_name);
  } else if (!m_options.m_python_script
                  .empty()) // we have a quick 1-line script, just use it
  {
    ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
    if (!interpreter) {
      result.AppendError("script interpreter missing - unable to generate "
                         "function wrapper.\n");
      result.SetStatus(eReturnStatusFailed);
      return false;
    }
    StringList funct_sl;
    funct_sl << m_options.m_python_script.c_str();
    std::string funct_name_str;
    if (!interpreter->GenerateTypeScriptFunction(funct_sl, funct_name_str)) {
      result.AppendError("unable to generate function wrapper.\n");
      result.SetStatus(eReturnStatusFailed);
      return false;
    }
    if (funct_name_str.empty()) {
      result.AppendError(
          "script interpreter failed to generate a valid function name.\n");
      result.SetStatus(eReturnStatusFailed);
      return false;
    }

    std::string code = "    " + m_options.m_python_script;

    script_format = std::make_shared<ScriptSummaryFormat>(
        m_options.m_flags, funct_name_str.c_str(), code.c_str());
  } else {
    // Use an IOHandler to grab Python code from the user
    ScriptAddOptions *options =
        new ScriptAddOptions(m_options.m_flags, m_options.m_regex,
                             m_options.m_name, m_options.m_category);

    for (auto &entry : command.entries()) {
      if (entry.ref().empty()) {
        result.AppendError("empty typenames not allowed");
        result.SetStatus(eReturnStatusFailed);
        return false;
      }

      options->m_target_types << std::string(entry.ref());
    }

    m_interpreter.GetPythonCommandsFromIOHandler(
        "    ",   // Prompt
        *this,    // IOHandlerDelegate
        options); // Baton for the "io_handler" that will be passed back into
                  // our IOHandlerDelegate functions
    result.SetStatus(eReturnStatusSuccessFinishNoResult);

    return result.Succeeded();
  }

  // if I am here, script_format must point to something good, so I can add
  // that as a script summary to all interested parties

  Status error;

  for (auto &entry : command.entries()) {
    CommandObjectTypeSummaryAdd::AddSummary(
        ConstString(entry.ref()), script_format,
        (m_options.m_regex ? eRegexSummary : eRegularSummary),
        m_options.m_category, &error);
    if (error.Fail()) {
      result.AppendError(error.AsCString());
      result.SetStatus(eReturnStatusFailed);
      return false;
    }
  }

  if (m_options.m_name) {
    AddSummary(m_options.m_name, script_format, eNamedSummary,
               m_options.m_category, &error);
    if (error.Fail()) {
      result.AppendError(error.AsCString());
      result.AppendError("added to types, but not given a name");
      result.SetStatus(eReturnStatusFailed);
      return false;
    }
  }

  return result.Succeeded();
}

#endif

bool CommandObjectTypeSummaryAdd::Execute_StringSummary(
    Args &command, CommandReturnObject &result) {
  const size_t argc = command.GetArgumentCount();

  if (argc < 1 && !m_options.m_name) {
    result.AppendErrorWithFormat("%s takes one or more args.\n",
                                 m_cmd_name.c_str());
    result.SetStatus(eReturnStatusFailed);
    return false;
  }

  if (!m_options.m_flags.GetShowMembersOneLiner() &&
      m_options.m_format_string.empty()) {
    result.AppendError("empty summary strings not allowed");
    result.SetStatus(eReturnStatusFailed);
    return false;
  }

  const char *format_cstr = (m_options.m_flags.GetShowMembersOneLiner()
                                 ? ""
                                 : m_options.m_format_string.c_str());

  // ${var%S} is an endless recursion, prevent it
  if (strcmp(format_cstr, "${var%S}") == 0) {
    result.AppendError("recursive summary not allowed");
    result.SetStatus(eReturnStatusFailed);
    return false;
  }

  std::unique_ptr<StringSummaryFormat> string_format(
      new StringSummaryFormat(m_options.m_flags, format_cstr));
  if (!string_format) {
    result.AppendError("summary creation failed");
    result.SetStatus(eReturnStatusFailed);
    return false;
  }
  if (string_format->m_error.Fail()) {
    result.AppendErrorWithFormat("syntax error: %s",
                                 string_format->m_error.AsCString("<unknown>"));
    result.SetStatus(eReturnStatusFailed);
    return false;
  }
  lldb::TypeSummaryImplSP entry(string_format.release());

  // now I have a valid format, let's add it to every type
  Status error;
  for (auto &arg_entry : command.entries()) {
    if (arg_entry.ref().empty()) {
      result.AppendError("empty typenames not allowed");
      result.SetStatus(eReturnStatusFailed);
      return false;
    }
    ConstString typeCS(arg_entry.ref());

    AddSummary(typeCS, entry,
               (m_options.m_regex ? eRegexSummary : eRegularSummary),
               m_options.m_category, &error);

    if (error.Fail()) {
      result.AppendError(error.AsCString());
      result.SetStatus(eReturnStatusFailed);
      return false;
    }
  }

  if (m_options.m_name) {
    AddSummary(m_options.m_name, entry, eNamedSummary, m_options.m_category,
               &error);
    if (error.Fail()) {
      result.AppendError(error.AsCString());
      result.AppendError("added to types, but not given a name");
      result.SetStatus(eReturnStatusFailed);
      return false;
    }
  }

  result.SetStatus(eReturnStatusSuccessFinishNoResult);
  return result.Succeeded();
}

CommandObjectTypeSummaryAdd::CommandObjectTypeSummaryAdd(
    CommandInterpreter &interpreter)
    : CommandObjectParsed(interpreter, "type summary add",
                          "Add a new summary style for a type.", nullptr),
      IOHandlerDelegateMultiline("DONE"), m_options(interpreter) {
  CommandArgumentEntry type_arg;
  CommandArgumentData type_style_arg;

  type_style_arg.arg_type = eArgTypeName;
  type_style_arg.arg_repetition = eArgRepeatPlus;

  type_arg.push_back(type_style_arg);

  m_arguments.push_back(type_arg);

  SetHelpLong(
      R"(
The following examples of 'type summary add' refer to this code snippet for context:

    struct JustADemo
    {
        int* ptr;
        float value;
        JustADemo(int p = 1, float v = 0.1) : ptr(new int(p)), value(v) {}
    };
    JustADemo demo_instance(42, 3.14);

    typedef JustADemo NewDemo;
    NewDemo new_demo_instance(42, 3.14);

(lldb) type summary add --summary-string "the answer is ${*var.ptr}" JustADemo

    Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42"

(lldb) type summary add --summary-string "the answer is ${*var.ptr}, and the question is ${var.value}" JustADemo

    Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42 and the question is 3.14"

)"
      "Alternatively, you could define formatting for all pointers to integers and \
rely on that when formatting JustADemo to obtain the same result:"
      R"(

(lldb) type summary add --summary-string "${var%V} -> ${*var}" "int *"
(lldb) type summary add --summary-string "the answer is ${var.ptr}, and the question is ${var.value}" JustADemo

)"
      "Type summaries are automatically applied to derived typedefs, so the examples \
above apply to both JustADemo and NewDemo.  The cascade option can be used to \
suppress this behavior:"
      R"(

(lldb) type summary add --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo -C no

    The summary will now be used for values of JustADemo but not NewDemo.

)"
      "By default summaries are shown for pointers and references to values of the \
specified type.  To suppress formatting for pointers use the -p option, or apply \
the corresponding -r option to suppress formatting for references:"
      R"(

(lldb) type summary add -p -r --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo

)"
      "One-line summaries including all fields in a type can be inferred without supplying an \
explicit summary string by passing the -c option:"
      R"(

(lldb) type summary add -c JustADemo
(lldb) frame variable demo_instance
(ptr=<address>, value=3.14)

)"
      "Type summaries normally suppress the nested display of individual fields.  To \
supply a summary to supplement the default structure add the -e option:"
      R"(

(lldb) type summary add -e --summary-string "*ptr = ${*var.ptr}" JustADemo

)"
      "Now when displaying JustADemo values the int* is displayed, followed by the \
standard LLDB sequence of children, one per line:"
      R"(

*ptr = 42 {
  ptr = <address>
  value = 3.14
}

)"
      "You can also add summaries written in Python.  These scripts use lldb public API to \
gather information from your variables and produce a meaningful summary.  To start a \
multi-line script use the -P option.  The function declaration will be displayed along with \
a comment describing the two arguments.  End your script with the  word 'DONE' on a line by \
itself:"
      R"(

(lldb) type summary add JustADemo -P
def function (valobj,internal_dict):
"""valobj: an SBValue which you want to provide a summary for
internal_dict: an LLDB support object not to be used"""
    value = valobj.GetChildMemberWithName('value');
    return 'My value is ' + value.GetValue();
    DONE

Alternatively, the -o option can be used when providing a simple one-line Python script:

(lldb) type summary add JustADemo -o "value = valobj.GetChildMemberWithName('value'); return 'My value is ' + value.GetValue();")");
}

bool CommandObjectTypeSummaryAdd::DoExecute(Args &command,
                                            CommandReturnObject &result) {
  WarnOnPotentialUnquotedUnsignedType(command, result);

  if (m_options.m_is_add_script) {
#if LLDB_ENABLE_PYTHON
    return Execute_ScriptSummary(command, result);
#else
    result.AppendError("python is disabled");
    result.SetStatus(eReturnStatusFailed);
    return false;
#endif
  }

  return Execute_StringSummary(command, result);
}

static bool FixArrayTypeNameWithRegex(ConstString &type_name) {
  llvm::StringRef type_name_ref(type_name.GetStringRef());

  if (type_name_ref.endswith("[]")) {
    std::string type_name_str(type_name.GetCString());
    type_name_str.resize(type_name_str.length() - 2);
    if (type_name_str.back() != ' ')
      type_name_str.append(" \\[[0-9]+\\]");
    else
      type_name_str.append("\\[[0-9]+\\]");
    type_name.SetCString(type_name_str.c_str());
    return true;
  }
  return false;
}

bool CommandObjectTypeSummaryAdd::AddSummary(ConstString type_name,
                                             TypeSummaryImplSP entry,
                                             SummaryFormatType type,
                                             std::string category_name,
                                             Status *error) {
  lldb::TypeCategoryImplSP category;
  DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()),
                                             category);

  if (type == eRegularSummary) {
    if (FixArrayTypeNameWithRegex(type_name))
      type = eRegexSummary;
  }

  if (type == eRegexSummary) {
    RegularExpression typeRX(type_name.GetStringRef());
    if (!typeRX.IsValid()) {
      if (error)
        error->SetErrorString(
            "regex format error (maybe this is not really a regex?)");
      return false;
    }

    category->GetRegexTypeSummariesContainer()->Delete(type_name);
    category->GetRegexTypeSummariesContainer()->Add(std::move(typeRX), entry);

    return true;
  } else if (type == eNamedSummary) {
    // system named summaries do not exist (yet?)
    DataVisualization::NamedSummaryFormats::Add(type_name, entry);
    return true;
  } else {
    category->GetTypeSummariesContainer()->Add(std::move(type_name), entry);
    return true;
  }
}

// CommandObjectTypeSummaryDelete

class CommandObjectTypeSummaryDelete : public CommandObjectTypeFormatterDelete {
public:
  CommandObjectTypeSummaryDelete(CommandInterpreter &interpreter)
      : CommandObjectTypeFormatterDelete(
            interpreter,
            eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary,
            "type summary delete", "Delete an existing summary for a type.") {}

  ~CommandObjectTypeSummaryDelete() override = default;

protected:
  bool FormatterSpecificDeletion(ConstString typeCS) override {
    if (m_options.m_language != lldb::eLanguageTypeUnknown)
      return false;
    return DataVisualization::NamedSummaryFormats::Delete(typeCS);
  }
};

class CommandObjectTypeSummaryClear : public CommandObjectTypeFormatterClear {
public:
  CommandObjectTypeSummaryClear(CommandInterpreter &interpreter)
      : CommandObjectTypeFormatterClear(
            interpreter,
            eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary,
            "type summary clear", "Delete all existing summaries.") {}

protected:
  void FormatterSpecificDeletion() override {
    DataVisualization::NamedSummaryFormats::Clear();
  }
};

// CommandObjectTypeSummaryList

class CommandObjectTypeSummaryList
    : public CommandObjectTypeFormatterList<TypeSummaryImpl> {
public:
  CommandObjectTypeSummaryList(CommandInterpreter &interpreter)
      : CommandObjectTypeFormatterList(interpreter, "type summary list",
                                       "Show a list of current summaries.") {}

protected:
  bool FormatterSpecificList(CommandReturnObject &result) override {
    if (DataVisualization::NamedSummaryFormats::GetCount() > 0) {
      result.GetOutputStream().Printf("Named summaries:\n");
      DataVisualization::NamedSummaryFormats::ForEach(
          [&result](const TypeMatcher &type_matcher,
                    const TypeSummaryImplSP &summary_sp) -> bool {
            result.GetOutputStream().Printf(
                "%s: %s\n", type_matcher.GetMatchString().GetCString(),
                summary_sp->GetDescription().c_str());
            return true;
          });
      return true;
    }
    return false;
  }
};

// CommandObjectTypeCategoryDefine
#define LLDB_OPTIONS_type_category_define
#include "CommandOptions.inc"

class CommandObjectTypeCategoryDefine : public CommandObjectParsed {
  class CommandOptions : public Options {
  public:
    CommandOptions()
        : Options(), m_define_enabled(false, false),
          m_cate_language(eLanguageTypeUnknown, eLanguageTypeUnknown) {}

    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      Status error;
      const int short_option = m_getopt_table[option_idx].val;

      switch (short_option) {
      case 'e':
        m_define_enabled.SetValueFromString(llvm::StringRef("true"));
        break;
      case 'l':
        error = m_cate_language.SetValueFromString(option_arg);
        break;
      default:
        llvm_unreachable("Unimplemented option");
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_define_enabled.Clear();
      m_cate_language.Clear();
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::makeArrayRef(g_type_category_define_options);
    }

    // Instance variables to hold the values for command options.

    OptionValueBoolean m_define_enabled;
    OptionValueLanguage m_cate_language;
  };

  CommandOptions m_options;

  Options *GetOptions() override { return &m_options; }

public:
  CommandObjectTypeCategoryDefine(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "type category define",
                            "Define a new category as a source of formatters.",
                            nullptr),
        m_options() {
    CommandArgumentEntry type_arg;
    CommandArgumentData type_style_arg;

    type_style_arg.arg_type = eArgTypeName;
    type_style_arg.arg_repetition = eArgRepeatPlus;

    type_arg.push_back(type_style_arg);

    m_arguments.push_back(type_arg);
  }

  ~CommandObjectTypeCategoryDefine() override = default;

  void
  HandleArgumentCompletion(CompletionRequest &request,
                           OptionElementVector &opt_element_vector) override {
    CommandCompletions::InvokeCommonCompletionCallbacks(
        GetCommandInterpreter(),
        CommandCompletions::eTypeCategoryNameCompletion, request, nullptr);
  }

protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    const size_t argc = command.GetArgumentCount();

    if (argc < 1) {
      result.AppendErrorWithFormat("%s takes 1 or more args.\n",
                                   m_cmd_name.c_str());
      result.SetStatus(eReturnStatusFailed);
      return false;
    }

    for (auto &entry : command.entries()) {
      TypeCategoryImplSP category_sp;
      if (DataVisualization::Categories::GetCategory(ConstString(entry.ref()),
                                                     category_sp) &&
          category_sp) {
        category_sp->AddLanguage(m_options.m_cate_language.GetCurrentValue());
        if (m_options.m_define_enabled.GetCurrentValue())
          DataVisualization::Categories::Enable(category_sp,
                                                TypeCategoryMap::Default);
      }
    }

    result.SetStatus(eReturnStatusSuccessFinishResult);
    return result.Succeeded();
  }
};

// CommandObjectTypeCategoryEnable
#define LLDB_OPTIONS_type_category_enable
#include "CommandOptions.inc"

class CommandObjectTypeCategoryEnable : public CommandObjectParsed {
  class CommandOptions : public Options {
  public:
    CommandOptions() : Options() {}

    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      Status error;
      const int short_option = m_getopt_table[option_idx].val;

      switch (short_option) {
      case 'l':
        if (!option_arg.empty()) {
          m_language = Language::GetLanguageTypeFromString(option_arg);
          if (m_language == lldb::eLanguageTypeUnknown)
            error.SetErrorStringWithFormat("unrecognized language '%s'",
                                           option_arg.str().c_str());
        }
        break;
      default:
        llvm_unreachable("Unimplemented option");
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_language = lldb::eLanguageTypeUnknown;
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::makeArrayRef(g_type_category_enable_options);
    }

    // Instance variables to hold the values for command options.

    lldb::LanguageType m_language;
  };

  CommandOptions m_options;

  Options *GetOptions() override { return &m_options; }

public:
  CommandObjectTypeCategoryEnable(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "type category enable",
                            "Enable a category as a source of formatters.",
                            nullptr),
        m_options() {
    CommandArgumentEntry type_arg;
    CommandArgumentData type_style_arg;

    type_style_arg.arg_type = eArgTypeName;
    type_style_arg.arg_repetition = eArgRepeatPlus;

    type_arg.push_back(type_style_arg);

    m_arguments.push_back(type_arg);
  }

  ~CommandObjectTypeCategoryEnable() override = default;

  void
  HandleArgumentCompletion(CompletionRequest &request,
                           OptionElementVector &opt_element_vector) override {
    CommandCompletions::InvokeCommonCompletionCallbacks(
        GetCommandInterpreter(),
        CommandCompletions::eTypeCategoryNameCompletion, request, nullptr);
  }

protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    const size_t argc = command.GetArgumentCount();

    if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) {
      result.AppendErrorWithFormat("%s takes arguments and/or a language",
                                   m_cmd_name.c_str());
      result.SetStatus(eReturnStatusFailed);
      return false;
    }

    if (argc == 1 && strcmp(command.GetArgumentAtIndex(0), "*") == 0) {
      DataVisualization::Categories::EnableStar();
    } else if (argc > 0) {
      for (int i = argc - 1; i >= 0; i--) {
        const char *typeA = command.GetArgumentAtIndex(i);
        ConstString typeCS(typeA);

        if (!typeCS) {
          result.AppendError("empty category name not allowed");
          result.SetStatus(eReturnStatusFailed);
          return false;
        }
        DataVisualization::Categories::Enable(typeCS);
        lldb::TypeCategoryImplSP cate;
        if (DataVisualization::Categories::GetCategory(typeCS, cate) && cate) {
          if (cate->GetCount() == 0) {
            result.AppendWarning("empty category enabled (typo?)");
          }
        }
      }
    }

    if (m_options.m_language != lldb::eLanguageTypeUnknown)
      DataVisualization::Categories::Enable(m_options.m_language);

    result.SetStatus(eReturnStatusSuccessFinishResult);
    return result.Succeeded();
  }
};

// CommandObjectTypeCategoryDelete

class CommandObjectTypeCategoryDelete : public CommandObjectParsed {
public:
  CommandObjectTypeCategoryDelete(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "type category delete",
                            "Delete a category and all associated formatters.",
                            nullptr) {
    CommandArgumentEntry type_arg;
    CommandArgumentData type_style_arg;

    type_style_arg.arg_type = eArgTypeName;
    type_style_arg.arg_repetition = eArgRepeatPlus;

    type_arg.push_back(type_style_arg);

    m_arguments.push_back(type_arg);
  }

  ~CommandObjectTypeCategoryDelete() override = default;

  void
  HandleArgumentCompletion(CompletionRequest &request,
                           OptionElementVector &opt_element_vector) override {
    CommandCompletions::InvokeCommonCompletionCallbacks(
        GetCommandInterpreter(),
        CommandCompletions::eTypeCategoryNameCompletion, request, nullptr);
  }

protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    const size_t argc = command.GetArgumentCount();

    if (argc < 1) {
      result.AppendErrorWithFormat("%s takes 1 or more arg.\n",
                                   m_cmd_name.c_str());
      result.SetStatus(eReturnStatusFailed);
      return false;
    }

    bool success = true;

    // the order is not relevant here
    for (int i = argc - 1; i >= 0; i--) {
      const char *typeA = command.GetArgumentAtIndex(i);
      ConstString typeCS(typeA);

      if (!typeCS) {
        result.AppendError("empty category name not allowed");
        result.SetStatus(eReturnStatusFailed);
        return false;
      }
      if (!DataVisualization::Categories::Delete(typeCS))
        success = false; // keep deleting even if we hit an error
    }
    if (success) {
      result.SetStatus(eReturnStatusSuccessFinishResult);
      return result.Succeeded();
    } else {
      result.AppendError("cannot delete one or more categories\n");
      result.SetStatus(eReturnStatusFailed);
      return false;
    }
  }
};

// CommandObjectTypeCategoryDisable
#define LLDB_OPTIONS_type_category_disable
#include "CommandOptions.inc"

class CommandObjectTypeCategoryDisable : public CommandObjectParsed {
  class CommandOptions : public Options {
  public:
    CommandOptions() : Options() {}

    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      Status error;
      const int short_option = m_getopt_table[option_idx].val;

      switch (short_option) {
      case 'l':
        if (!option_arg.empty()) {
          m_language = Language::GetLanguageTypeFromString(option_arg);
          if (m_language == lldb::eLanguageTypeUnknown)
            error.SetErrorStringWithFormat("unrecognized language '%s'",
                                           option_arg.str().c_str());
        }
        break;
      default:
        llvm_unreachable("Unimplemented option");
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_language = lldb::eLanguageTypeUnknown;
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::makeArrayRef(g_type_category_disable_options);
    }

    // Instance variables to hold the values for command options.

    lldb::LanguageType m_language;
  };

  CommandOptions m_options;

  Options *GetOptions() override { return &m_options; }

public:
  CommandObjectTypeCategoryDisable(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "type category disable",
                            "Disable a category as a source of formatters.",
                            nullptr),
        m_options() {
    CommandArgumentEntry type_arg;
    CommandArgumentData type_style_arg;

    type_style_arg.arg_type = eArgTypeName;
    type_style_arg.arg_repetition = eArgRepeatPlus;

    type_arg.push_back(type_style_arg);

    m_arguments.push_back(type_arg);
  }

  ~CommandObjectTypeCategoryDisable() override = default;

  void
  HandleArgumentCompletion(CompletionRequest &request,
                           OptionElementVector &opt_element_vector) override {
    CommandCompletions::InvokeCommonCompletionCallbacks(
        GetCommandInterpreter(),
        CommandCompletions::eTypeCategoryNameCompletion, request, nullptr);
  }

protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    const size_t argc = command.GetArgumentCount();

    if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) {
      result.AppendErrorWithFormat("%s takes arguments and/or a language",
                                   m_cmd_name.c_str());
      result.SetStatus(eReturnStatusFailed);
      return false;
    }

    if (argc == 1 && strcmp(command.GetArgumentAtIndex(0), "*") == 0) {
      DataVisualization::Categories::DisableStar();
    } else if (argc > 0) {
      // the order is not relevant here
      for (int i = argc - 1; i >= 0; i--) {
        const char *typeA = command.GetArgumentAtIndex(i);
        ConstString typeCS(typeA);

        if (!typeCS) {
          result.AppendError("empty category name not allowed");
          result.SetStatus(eReturnStatusFailed);
          return false;
        }
        DataVisualization::Categories::Disable(typeCS);
      }
    }

    if (m_options.m_language != lldb::eLanguageTypeUnknown)
      DataVisualization::Categories::Disable(m_options.m_language);

    result.SetStatus(eReturnStatusSuccessFinishResult);
    return result.Succeeded();
  }
};

// CommandObjectTypeCategoryList

class CommandObjectTypeCategoryList : public CommandObjectParsed {
public:
  CommandObjectTypeCategoryList(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "type category list",
                            "Provide a list of all existing categories.",
                            nullptr) {
    CommandArgumentEntry type_arg;
    CommandArgumentData type_style_arg;

    type_style_arg.arg_type = eArgTypeName;
    type_style_arg.arg_repetition = eArgRepeatOptional;

    type_arg.push_back(type_style_arg);

    m_arguments.push_back(type_arg);
  }

  ~CommandObjectTypeCategoryList() override = default;

  void
  HandleArgumentCompletion(CompletionRequest &request,
                           OptionElementVector &opt_element_vector) override {
    if (request.GetCursorIndex())
      return;
    CommandCompletions::InvokeCommonCompletionCallbacks(
        GetCommandInterpreter(),
        CommandCompletions::eTypeCategoryNameCompletion, request, nullptr);
  }

protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    const size_t argc = command.GetArgumentCount();

    std::unique_ptr<RegularExpression> regex;

    if (argc == 1) {
      const char *arg = command.GetArgumentAtIndex(0);
      regex = std::make_unique<RegularExpression>(
          llvm::StringRef::withNullAsEmpty(arg));
      if (!regex->IsValid()) {
        result.AppendErrorWithFormat(
            "syntax error in category regular expression '%s'", arg);
        result.SetStatus(eReturnStatusFailed);
        return false;
      }
    } else if (argc != 0) {
      result.AppendErrorWithFormat("%s takes 0 or one arg.\n",
                                   m_cmd_name.c_str());
      result.SetStatus(eReturnStatusFailed);
      return false;
    }

    DataVisualization::Categories::ForEach(
        [&regex, &result](const lldb::TypeCategoryImplSP &category_sp) -> bool {
          if (regex) {
            bool escape = true;
            if (regex->GetText() == category_sp->GetName()) {
              escape = false;
            } else if (regex->Execute(llvm::StringRef::withNullAsEmpty(
                           category_sp->GetName()))) {
              escape = false;
            }

            if (escape)
              return true;
          }

          result.GetOutputStream().Printf(
              "Category: %s\n", category_sp->GetDescription().c_str());

          return true;
        });

    result.SetStatus(eReturnStatusSuccessFinishResult);
    return result.Succeeded();
  }
};

// CommandObjectTypeFilterList

class CommandObjectTypeFilterList
    : public CommandObjectTypeFormatterList<TypeFilterImpl> {
public:
  CommandObjectTypeFilterList(CommandInterpreter &interpreter)
      : CommandObjectTypeFormatterList(interpreter, "type filter list",
                                       "Show a list of current filters.") {}
};

#if LLDB_ENABLE_PYTHON

// CommandObjectTypeSynthList

class CommandObjectTypeSynthList
    : public CommandObjectTypeFormatterList<SyntheticChildren> {
public:
  CommandObjectTypeSynthList(CommandInterpreter &interpreter)
      : CommandObjectTypeFormatterList(
            interpreter, "type synthetic list",
            "Show a list of current synthetic providers.") {}
};

#endif

// CommandObjectTypeFilterDelete

class CommandObjectTypeFilterDelete : public CommandObjectTypeFormatterDelete {
public:
  CommandObjectTypeFilterDelete(CommandInterpreter &interpreter)
      : CommandObjectTypeFormatterDelete(
            interpreter,
            eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter,
            "type filter delete", "Delete an existing filter for a type.") {}

  ~CommandObjectTypeFilterDelete() override = default;
};

#if LLDB_ENABLE_PYTHON

// CommandObjectTypeSynthDelete

class CommandObjectTypeSynthDelete : public CommandObjectTypeFormatterDelete {
public:
  CommandObjectTypeSynthDelete(CommandInterpreter &interpreter)
      : CommandObjectTypeFormatterDelete(
            interpreter,
            eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth,
            "type synthetic delete",
            "Delete an existing synthetic provider for a type.") {}

  ~CommandObjectTypeSynthDelete() override = default;
};

#endif

// CommandObjectTypeFilterClear

class CommandObjectTypeFilterClear : public CommandObjectTypeFormatterClear {
public:
  CommandObjectTypeFilterClear(CommandInterpreter &interpreter)
      : CommandObjectTypeFormatterClear(
            interpreter,
            eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter,
            "type filter clear", "Delete all existing filter.") {}
};

#if LLDB_ENABLE_PYTHON
// CommandObjectTypeSynthClear

class CommandObjectTypeSynthClear : public CommandObjectTypeFormatterClear {
public:
  CommandObjectTypeSynthClear(CommandInterpreter &interpreter)
      : CommandObjectTypeFormatterClear(
            interpreter,
            eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth,
            "type synthetic clear",
            "Delete all existing synthetic providers.") {}
};

bool CommandObjectTypeSynthAdd::Execute_HandwritePython(
    Args &command, CommandReturnObject &result) {
  SynthAddOptions *options = new SynthAddOptions(
      m_options.m_skip_pointers, m_options.m_skip_references,
      m_options.m_cascade, m_options.m_regex, m_options.m_category);

  for (auto &entry : command.entries()) {
    if (entry.ref().empty()) {
      result.AppendError("empty typenames not allowed");
      result.SetStatus(eReturnStatusFailed);
      return false;
    }

    options->m_target_types << std::string(entry.ref());
  }

  m_interpreter.GetPythonCommandsFromIOHandler(
      "    ",   // Prompt
      *this,    // IOHandlerDelegate
      options); // Baton for the "io_handler" that will be passed back into our
                // IOHandlerDelegate functions
  result.SetStatus(eReturnStatusSuccessFinishNoResult);
  return result.Succeeded();
}

bool CommandObjectTypeSynthAdd::Execute_PythonClass(
    Args &command, CommandReturnObject &result) {
  const size_t argc = command.GetArgumentCount();

  if (argc < 1) {
    result.AppendErrorWithFormat("%s takes one or more args.\n",
                                 m_cmd_name.c_str());
    result.SetStatus(eReturnStatusFailed);
    return false;
  }

  if (m_options.m_class_name.empty() && !m_options.m_input_python) {
    result.AppendErrorWithFormat("%s needs either a Python class name or -P to "
                                 "directly input Python code.\n",
                                 m_cmd_name.c_str());
    result.SetStatus(eReturnStatusFailed);
    return false;
  }

  SyntheticChildrenSP entry;

  ScriptedSyntheticChildren *impl = new ScriptedSyntheticChildren(
      SyntheticChildren::Flags()
          .SetCascades(m_options.m_cascade)
          .SetSkipPointers(m_options.m_skip_pointers)
          .SetSkipReferences(m_options.m_skip_references),
      m_options.m_class_name.c_str());

  entry.reset(impl);

  ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();

  if (interpreter &&
      !interpreter->CheckObjectExists(impl->GetPythonClassName()))
    result.AppendWarning("The provided class does not exist - please define it "
                         "before attempting to use this synthetic provider");

  // now I have a valid provider, let's add it to every type

  lldb::TypeCategoryImplSP category;
  DataVisualization::Categories::GetCategory(
      ConstString(m_options.m_category.c_str()), category);

  Status error;

  for (auto &arg_entry : command.entries()) {
    if (arg_entry.ref().empty()) {
      result.AppendError("empty typenames not allowed");
      result.SetStatus(eReturnStatusFailed);
      return false;
    }

    ConstString typeCS(arg_entry.ref());
    if (!AddSynth(typeCS, entry,
                  m_options.m_regex ? eRegexSynth : eRegularSynth,
                  m_options.m_category, &error)) {
      result.AppendError(error.AsCString());
      result.SetStatus(eReturnStatusFailed);
      return false;
    }
  }

  result.SetStatus(eReturnStatusSuccessFinishNoResult);
  return result.Succeeded();
}

CommandObjectTypeSynthAdd::CommandObjectTypeSynthAdd(
    CommandInterpreter &interpreter)
    : CommandObjectParsed(interpreter, "type synthetic add",
                          "Add a new synthetic provider for a type.", nullptr),
      IOHandlerDelegateMultiline("DONE"), m_options() {
  CommandArgumentEntry type_arg;
  CommandArgumentData type_style_arg;

  type_style_arg.arg_type = eArgTypeName;
  type_style_arg.arg_repetition = eArgRepeatPlus;

  type_arg.push_back(type_style_arg);

  m_arguments.push_back(type_arg);
}

bool CommandObjectTypeSynthAdd::AddSynth(ConstString type_name,
                                         SyntheticChildrenSP entry,
                                         SynthFormatType type,
                                         std::string category_name,
                                         Status *error) {
  lldb::TypeCategoryImplSP category;
  DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()),
                                             category);

  if (type == eRegularSynth) {
    if (FixArrayTypeNameWithRegex(type_name))
      type = eRegexSynth;
  }

  if (category->AnyMatches(
          type_name, eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter,
          false)) {
    if (error)
      error->SetErrorStringWithFormat("cannot add synthetic for type %s when "
                                      "filter is defined in same category!",
                                      type_name.AsCString());
    return false;
  }

  if (type == eRegexSynth) {
    RegularExpression typeRX(type_name.GetStringRef());
    if (!typeRX.IsValid()) {
      if (error)
        error->SetErrorString(
            "regex format error (maybe this is not really a regex?)");
      return false;
    }

    category->GetRegexTypeSyntheticsContainer()->Delete(type_name);
    category->GetRegexTypeSyntheticsContainer()->Add(std::move(typeRX), entry);

    return true;
  } else {
    category->GetTypeSyntheticsContainer()->Add(std::move(type_name), entry);
    return true;
  }
}

#endif
#define LLDB_OPTIONS_type_filter_add
#include "CommandOptions.inc"

class CommandObjectTypeFilterAdd : public CommandObjectParsed {
private:
  class CommandOptions : public Options {
    typedef std::vector<std::string> option_vector;

  public:
    CommandOptions() : Options() {}

    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      Status error;
      const int short_option = m_getopt_table[option_idx].val;
      bool success;

      switch (short_option) {
      case 'C':
        m_cascade = OptionArgParser::ToBoolean(option_arg, true, &success);
        if (!success)
          error.SetErrorStringWithFormat("invalid value for cascade: %s",
                                         option_arg.str().c_str());
        break;
      case 'c':
        m_expr_paths.push_back(std::string(option_arg));
        has_child_list = true;
        break;
      case 'p':
        m_skip_pointers = true;
        break;
      case 'r':
        m_skip_references = true;
        break;
      case 'w':
        m_category = std::string(option_arg);
        break;
      case 'x':
        m_regex = true;
        break;
      default:
        llvm_unreachable("Unimplemented option");
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_cascade = true;
      m_skip_pointers = false;
      m_skip_references = false;
      m_category = "default";
      m_expr_paths.clear();
      has_child_list = false;
      m_regex = false;
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::makeArrayRef(g_type_filter_add_options);
    }

    // Instance variables to hold the values for command options.

    bool m_cascade;
    bool m_skip_references;
    bool m_skip_pointers;
    bool m_input_python;
    option_vector m_expr_paths;
    std::string m_category;
    bool has_child_list;
    bool m_regex;

    typedef option_vector::iterator ExpressionPathsIterator;
  };

  CommandOptions m_options;

  Options *GetOptions() override { return &m_options; }

  enum FilterFormatType { eRegularFilter, eRegexFilter };

  bool AddFilter(ConstString type_name, TypeFilterImplSP entry,
                 FilterFormatType type, std::string category_name,
                 Status *error) {
    lldb::TypeCategoryImplSP category;
    DataVisualization::Categories::GetCategory(
        ConstString(category_name.c_str()), category);

    if (type == eRegularFilter) {
      if (FixArrayTypeNameWithRegex(type_name))
        type = eRegexFilter;
    }

    if (category->AnyMatches(
            type_name, eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth,
            false)) {
      if (error)
        error->SetErrorStringWithFormat("cannot add filter for type %s when "
                                        "synthetic is defined in same "
                                        "category!",
                                        type_name.AsCString());
      return false;
    }

    if (type == eRegexFilter) {
      RegularExpression typeRX(type_name.GetStringRef());
      if (!typeRX.IsValid()) {
        if (error)
          error->SetErrorString(
              "regex format error (maybe this is not really a regex?)");
        return false;
      }

      category->GetRegexTypeFiltersContainer()->Delete(type_name);
      category->GetRegexTypeFiltersContainer()->Add(std::move(typeRX), entry);

      return true;
    } else {
      category->GetTypeFiltersContainer()->Add(std::move(type_name), entry);
      return true;
    }
  }

public:
  CommandObjectTypeFilterAdd(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "type filter add",
                            "Add a new filter for a type.", nullptr),
        m_options() {
    CommandArgumentEntry type_arg;
    CommandArgumentData type_style_arg;

    type_style_arg.arg_type = eArgTypeName;
    type_style_arg.arg_repetition = eArgRepeatPlus;

    type_arg.push_back(type_style_arg);

    m_arguments.push_back(type_arg);

    SetHelpLong(
        R"(
The following examples of 'type filter add' refer to this code snippet for context:

    class Foo {
        int a;
        int b;
        int c;
        int d;
        int e;
        int f;
        int g;
        int h;
        int i;
    }
    Foo my_foo;

Adding a simple filter:

(lldb) type filter add --child a --child g Foo
(lldb) frame variable my_foo

)"
        "Produces output where only a and g are displayed.  Other children of my_foo \
(b, c, d, e, f, h and i) are available by asking for them explicitly:"
        R"(

(lldb) frame variable my_foo.b my_foo.c my_foo.i

)"
        "The formatting option --raw on frame variable bypasses the filter, showing \
all children of my_foo as if no filter was defined:"
        R"(

(lldb) frame variable my_foo --raw)");
  }

  ~CommandObjectTypeFilterAdd() override = default;

protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    const size_t argc = command.GetArgumentCount();

    if (argc < 1) {
      result.AppendErrorWithFormat("%s takes one or more args.\n",
                                   m_cmd_name.c_str());
      result.SetStatus(eReturnStatusFailed);
      return false;
    }

    if (m_options.m_expr_paths.empty()) {
      result.AppendErrorWithFormat("%s needs one or more children.\n",
                                   m_cmd_name.c_str());
      result.SetStatus(eReturnStatusFailed);
      return false;
    }

    TypeFilterImplSP entry(new TypeFilterImpl(
        SyntheticChildren::Flags()
            .SetCascades(m_options.m_cascade)
            .SetSkipPointers(m_options.m_skip_pointers)
            .SetSkipReferences(m_options.m_skip_references)));

    // go through the expression paths
    CommandOptions::ExpressionPathsIterator begin,
        end = m_options.m_expr_paths.end();

    for (begin = m_options.m_expr_paths.begin(); begin != end; begin++)
      entry->AddExpressionPath(*begin);

    // now I have a valid provider, let's add it to every type

    lldb::TypeCategoryImplSP category;
    DataVisualization::Categories::GetCategory(
        ConstString(m_options.m_category.c_str()), category);

    Status error;

    WarnOnPotentialUnquotedUnsignedType(command, result);

    for (auto &arg_entry : command.entries()) {
      if (arg_entry.ref().empty()) {
        result.AppendError("empty typenames not allowed");
        result.SetStatus(eReturnStatusFailed);
        return false;
      }

      ConstString typeCS(arg_entry.ref());
      if (!AddFilter(typeCS, entry,
                     m_options.m_regex ? eRegexFilter : eRegularFilter,
                     m_options.m_category, &error)) {
        result.AppendError(error.AsCString());
        result.SetStatus(eReturnStatusFailed);
        return false;
      }
    }

    result.SetStatus(eReturnStatusSuccessFinishNoResult);
    return result.Succeeded();
  }
};

// "type lookup"
#define LLDB_OPTIONS_type_lookup
#include "CommandOptions.inc"

class CommandObjectTypeLookup : public CommandObjectRaw {
protected:
  // this function is allowed to do a more aggressive job at guessing languages
  // than the expression parser is comfortable with - so leave the original
  // call alone and add one that is specific to type lookup
  lldb::LanguageType GuessLanguage(StackFrame *frame) {
    lldb::LanguageType lang_type = lldb::eLanguageTypeUnknown;

    if (!frame)
      return lang_type;

    lang_type = frame->GuessLanguage();
    if (lang_type != lldb::eLanguageTypeUnknown)
      return lang_type;

    Symbol *s = frame->GetSymbolContext(eSymbolContextSymbol).symbol;
    if (s)
      lang_type = s->GetMangled().GuessLanguage();

    return lang_type;
  }

  class CommandOptions : public OptionGroup {
  public:
    CommandOptions()
        : OptionGroup(), m_show_help(false), m_language(eLanguageTypeUnknown) {}

    ~CommandOptions() override = default;

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::makeArrayRef(g_type_lookup_options);
    }

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
                          ExecutionContext *execution_context) override {
      Status error;

      const int short_option = g_type_lookup_options[option_idx].short_option;

      switch (short_option) {
      case 'h':
        m_show_help = true;
        break;

      case 'l':
        m_language = Language::GetLanguageTypeFromString(option_value);
        break;

      default:
        llvm_unreachable("Unimplemented option");
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_show_help = false;
      m_language = eLanguageTypeUnknown;
    }

    // Options table: Required for subclasses of Options.

    bool m_show_help;
    lldb::LanguageType m_language;
  };

  OptionGroupOptions m_option_group;
  CommandOptions m_command_options;

public:
  CommandObjectTypeLookup(CommandInterpreter &interpreter)
      : CommandObjectRaw(interpreter, "type lookup",
                         "Lookup types and declarations in the current target, "
                         "following language-specific naming conventions.",
                         "type lookup <type-specifier>",
                         eCommandRequiresTarget),
        m_option_group(), m_command_options() {
    m_option_group.Append(&m_command_options);
    m_option_group.Finalize();
  }

  ~CommandObjectTypeLookup() override = default;

  Options *GetOptions() override { return &m_option_group; }

  llvm::StringRef GetHelpLong() override {
    if (!m_cmd_help_long.empty())
      return m_cmd_help_long;

    StreamString stream;
    Language::ForEach([&](Language *lang) {
      if (const char *help = lang->GetLanguageSpecificTypeLookupHelp())
        stream.Printf("%s\n", help);
      return true;
    });

    m_cmd_help_long = std::string(stream.GetString());
    return m_cmd_help_long;
  }

  bool DoExecute(llvm::StringRef raw_command_line,
                 CommandReturnObject &result) override {
    if (raw_command_line.empty()) {
      result.SetError(
          "type lookup cannot be invoked without a type name as argument");
      return false;
    }

    auto exe_ctx = GetCommandInterpreter().GetExecutionContext();
    m_option_group.NotifyOptionParsingStarting(&exe_ctx);

    OptionsWithRaw args(raw_command_line);
    const char *name_of_type = args.GetRawPart().c_str();

    if (args.HasArgs())
      if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group,
                                 exe_ctx))
        return false;

    ExecutionContextScope *best_scope = exe_ctx.GetBestExecutionContextScope();

    bool any_found = false;

    std::vector<Language *> languages;

    bool is_global_search = false;
    LanguageType guessed_language = lldb::eLanguageTypeUnknown;

    if ((is_global_search =
             (m_command_options.m_language == eLanguageTypeUnknown))) {
      Language::ForEach([&](Language *lang) {
        languages.push_back(lang);
        return true;
      });
    } else {
      languages.push_back(Language::FindPlugin(m_command_options.m_language));
    }

    // This is not the most efficient way to do this, but we support very few
    // languages so the cost of the sort is going to be dwarfed by the actual
    // lookup anyway
    if (StackFrame *frame = m_exe_ctx.GetFramePtr()) {
      guessed_language = GuessLanguage(frame);
      if (guessed_language != eLanguageTypeUnknown) {
        llvm::sort(
            languages.begin(), languages.end(),
            [guessed_language](Language *lang1, Language *lang2) -> bool {
              if (!lang1 || !lang2)
                return false;
              LanguageType lt1 = lang1->GetLanguageType();
              LanguageType lt2 = lang2->GetLanguageType();
              if (lt1 == guessed_language)
                return true; // make the selected frame's language come first
              if (lt2 == guessed_language)
                return false; // make the selected frame's language come first
              return (lt1 < lt2); // normal comparison otherwise
            });
      }
    }

    bool is_first_language = true;

    for (Language *language : languages) {
      if (!language)
        continue;

      if (auto scavenger = language->GetTypeScavenger()) {
        Language::TypeScavenger::ResultSet search_results;
        if (scavenger->Find(best_scope, name_of_type, search_results) > 0) {
          for (const auto &search_result : search_results) {
            if (search_result && search_result->IsValid()) {
              any_found = true;
              search_result->DumpToStream(result.GetOutputStream(),
                                          this->m_command_options.m_show_help);
            }
          }
        }
      }
      // this is "type lookup SomeName" and we did find a match, so get out
      if (any_found && is_global_search)
        break;
      else if (is_first_language && is_global_search &&
               guessed_language != lldb::eLanguageTypeUnknown) {
        is_first_language = false;
        result.GetOutputStream().Printf(
            "no type was found in the current language %s matching '%s'; "
            "performing a global search across all languages\n",
            Language::GetNameForLanguageType(guessed_language), name_of_type);
      }
    }

    if (!any_found)
      result.AppendMessageWithFormat("no type was found matching '%s'\n",
                                     name_of_type);

    result.SetStatus(any_found ? lldb::eReturnStatusSuccessFinishResult
                               : lldb::eReturnStatusSuccessFinishNoResult);
    return true;
  }
};

template <typename FormatterType>
class CommandObjectFormatterInfo : public CommandObjectRaw {
public:
  typedef std::function<typename FormatterType::SharedPointer(ValueObject &)>
      DiscoveryFunction;
  CommandObjectFormatterInfo(CommandInterpreter &interpreter,
                             const char *formatter_name,
                             DiscoveryFunction discovery_func)
      : CommandObjectRaw(interpreter, "", "", "", eCommandRequiresFrame),
        m_formatter_name(formatter_name ? formatter_name : ""),
        m_discovery_function(discovery_func) {
    StreamString name;
    name.Printf("type %s info", formatter_name);
    SetCommandName(name.GetString());
    StreamString help;
    help.Printf("This command evaluates the provided expression and shows "
                "which %s is applied to the resulting value (if any).",
                formatter_name);
    SetHelp(help.GetString());
    StreamString syntax;
    syntax.Printf("type %s info <expr>", formatter_name);
    SetSyntax(syntax.GetString());
  }

  ~CommandObjectFormatterInfo() override = default;

protected:
  bool DoExecute(llvm::StringRef command,
                 CommandReturnObject &result) override {
    TargetSP target_sp = GetDebugger().GetSelectedTarget();
    Thread *thread = GetDefaultThread();
    if (!thread) {
      result.AppendError("no default thread");
      result.SetStatus(lldb::eReturnStatusFailed);
      return false;
    }

    StackFrameSP frame_sp = thread->GetSelectedFrame();
    ValueObjectSP result_valobj_sp;
    EvaluateExpressionOptions options;
    lldb::ExpressionResults expr_result = target_sp->EvaluateExpression(
        command, frame_sp.get(), result_valobj_sp, options);
    if (expr_result == eExpressionCompleted && result_valobj_sp) {
      result_valobj_sp =
          result_valobj_sp->GetQualifiedRepresentationIfAvailable(
              target_sp->GetPreferDynamicValue(),
              target_sp->GetEnableSyntheticValue());
      typename FormatterType::SharedPointer formatter_sp =
          m_discovery_function(*result_valobj_sp);
      if (formatter_sp) {
        std::string description(formatter_sp->GetDescription());
        result.GetOutputStream()
            << m_formatter_name << " applied to ("
            << result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>")
            << ") " << command << " is: " << description << "\n";
        result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
      } else {
        result.GetOutputStream()
            << "no " << m_formatter_name << " applies to ("
            << result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>")
            << ") " << command << "\n";
        result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
      }
      return true;
    } else {
      result.AppendError("failed to evaluate expression");
      result.SetStatus(lldb::eReturnStatusFailed);
      return false;
    }
  }

private:
  std::string m_formatter_name;
  DiscoveryFunction m_discovery_function;
};

class CommandObjectTypeFormat : public CommandObjectMultiword {
public:
  CommandObjectTypeFormat(CommandInterpreter &interpreter)
      : CommandObjectMultiword(
            interpreter, "type format",
            "Commands for customizing value display formats.",
            "type format [<sub-command-options>] ") {
    LoadSubCommand(
        "add", CommandObjectSP(new CommandObjectTypeFormatAdd(interpreter)));
    LoadSubCommand("clear", CommandObjectSP(
                                new CommandObjectTypeFormatClear(interpreter)));
    LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFormatDelete(
                                 interpreter)));
    LoadSubCommand(
        "list", CommandObjectSP(new CommandObjectTypeFormatList(interpreter)));
    LoadSubCommand(
        "info", CommandObjectSP(new CommandObjectFormatterInfo<TypeFormatImpl>(
                    interpreter, "format",
                    [](ValueObject &valobj) -> TypeFormatImpl::SharedPointer {
                      return valobj.GetValueFormat();
                    })));
  }

  ~CommandObjectTypeFormat() override = default;
};

#if LLDB_ENABLE_PYTHON

class CommandObjectTypeSynth : public CommandObjectMultiword {
public:
  CommandObjectTypeSynth(CommandInterpreter &interpreter)
      : CommandObjectMultiword(
            interpreter, "type synthetic",
            "Commands for operating on synthetic type representations.",
            "type synthetic [<sub-command-options>] ") {
    LoadSubCommand("add",
                   CommandObjectSP(new CommandObjectTypeSynthAdd(interpreter)));
    LoadSubCommand(
        "clear", CommandObjectSP(new CommandObjectTypeSynthClear(interpreter)));
    LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSynthDelete(
                                 interpreter)));
    LoadSubCommand(
        "list", CommandObjectSP(new CommandObjectTypeSynthList(interpreter)));
    LoadSubCommand(
        "info",
        CommandObjectSP(new CommandObjectFormatterInfo<SyntheticChildren>(
            interpreter, "synthetic",
            [](ValueObject &valobj) -> SyntheticChildren::SharedPointer {
              return valobj.GetSyntheticChildren();
            })));
  }

  ~CommandObjectTypeSynth() override = default;
};

#endif

class CommandObjectTypeFilter : public CommandObjectMultiword {
public:
  CommandObjectTypeFilter(CommandInterpreter &interpreter)
      : CommandObjectMultiword(interpreter, "type filter",
                               "Commands for operating on type filters.",
                               "type synthetic [<sub-command-options>] ") {
    LoadSubCommand(
        "add", CommandObjectSP(new CommandObjectTypeFilterAdd(interpreter)));
    LoadSubCommand("clear", CommandObjectSP(
                                new CommandObjectTypeFilterClear(interpreter)));
    LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFilterDelete(
                                 interpreter)));
    LoadSubCommand(
        "list", CommandObjectSP(new CommandObjectTypeFilterList(interpreter)));
  }

  ~CommandObjectTypeFilter() override = default;
};

class CommandObjectTypeCategory : public CommandObjectMultiword {
public:
  CommandObjectTypeCategory(CommandInterpreter &interpreter)
      : CommandObjectMultiword(interpreter, "type category",
                               "Commands for operating on type categories.",
                               "type category [<sub-command-options>] ") {
    LoadSubCommand(
        "define",
        CommandObjectSP(new CommandObjectTypeCategoryDefine(interpreter)));
    LoadSubCommand(
        "enable",
        CommandObjectSP(new CommandObjectTypeCategoryEnable(interpreter)));
    LoadSubCommand(
        "disable",
        CommandObjectSP(new CommandObjectTypeCategoryDisable(interpreter)));
    LoadSubCommand(
        "delete",
        CommandObjectSP(new CommandObjectTypeCategoryDelete(interpreter)));
    LoadSubCommand("list", CommandObjectSP(
                               new CommandObjectTypeCategoryList(interpreter)));
  }

  ~CommandObjectTypeCategory() override = default;
};

class CommandObjectTypeSummary : public CommandObjectMultiword {
public:
  CommandObjectTypeSummary(CommandInterpreter &interpreter)
      : CommandObjectMultiword(
            interpreter, "type summary",
            "Commands for editing variable summary display options.",
            "type summary [<sub-command-options>] ") {
    LoadSubCommand(
        "add", CommandObjectSP(new CommandObjectTypeSummaryAdd(interpreter)));
    LoadSubCommand("clear", CommandObjectSP(new CommandObjectTypeSummaryClear(
                                interpreter)));
    LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSummaryDelete(
                                 interpreter)));
    LoadSubCommand(
        "list", CommandObjectSP(new CommandObjectTypeSummaryList(interpreter)));
    LoadSubCommand(
        "info", CommandObjectSP(new CommandObjectFormatterInfo<TypeSummaryImpl>(
                    interpreter, "summary",
                    [](ValueObject &valobj) -> TypeSummaryImpl::SharedPointer {
                      return valobj.GetSummaryFormat();
                    })));
  }

  ~CommandObjectTypeSummary() override = default;
};

// CommandObjectType

CommandObjectType::CommandObjectType(CommandInterpreter &interpreter)
    : CommandObjectMultiword(interpreter, "type",
                             "Commands for operating on the type system.",
                             "type [<sub-command-options>]") {
  LoadSubCommand("category",
                 CommandObjectSP(new CommandObjectTypeCategory(interpreter)));
  LoadSubCommand("filter",
                 CommandObjectSP(new CommandObjectTypeFilter(interpreter)));
  LoadSubCommand("format",
                 CommandObjectSP(new CommandObjectTypeFormat(interpreter)));
  LoadSubCommand("summary",
                 CommandObjectSP(new CommandObjectTypeSummary(interpreter)));
#if LLDB_ENABLE_PYTHON
  LoadSubCommand("synthetic",
                 CommandObjectSP(new CommandObjectTypeSynth(interpreter)));
#endif
  LoadSubCommand("lookup",
                 CommandObjectSP(new CommandObjectTypeLookup(interpreter)));
}

CommandObjectType::~CommandObjectType() = default;
