//===-- 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>

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, 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;

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](
                      ConstString name,
                      const FormatterSharedPointer &format_sp) -> bool {
          if (formatter_regex) {
            bool escape = true;
            if (name.GetStringRef() == formatter_regex->GetText()) {
              escape = false;
            } else if (formatter_regex->Execute(name.GetStringRef())) {
              escape = false;
            }

            if (escape)
              return true;
          }

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

      foreach
        .SetWithRegex([&result, &formatter_regex, &any_printed](
                          const RegularExpression &regex,
                          const FormatterSharedPointer &format_sp) -> bool {
          if (formatter_regex) {
            bool escape = true;
            if (regex.GetText() == formatter_regex->GetText()) {
              escape = false;
            } else if (formatter_regex->Execute(regex.GetText())) {
              escape = false;
            }

            if (escape)
              return true;
          }

          any_printed = true;
          result.GetOutputStream().Printf("%s: %s\n",
                                          regex.GetText().str().c_str(),
                                          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](ConstString name,
                    const TypeSummaryImplSP &summary_sp) -> bool {
            result.GetOutputStream().Printf(
                "%s: %s\n", name.AsCString(),
                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;

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;

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;

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;

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;

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;
