brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.2 KiB · f1dbd03 Raw
211 lines · cpp
1//===-- CommandObjectHelp.cpp ---------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "CommandObjectHelp.h"10#include "lldb/Interpreter/CommandInterpreter.h"11#include "lldb/Interpreter/CommandOptionArgumentTable.h"12#include "lldb/Interpreter/CommandReturnObject.h"13 14using namespace lldb;15using namespace lldb_private;16 17// CommandObjectHelp18 19void CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage(20    Stream *s, llvm::StringRef command, llvm::StringRef prefix,21    llvm::StringRef subcommand, bool include_upropos,22    bool include_type_lookup) {23  if (!s || command.empty())24    return;25 26  std::string command_str = command.str();27  std::string prefix_str = prefix.str();28  std::string subcommand_str = subcommand.str();29  const std::string &lookup_str =30      !subcommand_str.empty() ? subcommand_str : command_str;31  s->Printf("'%s' is not a known command.\n", command_str.c_str());32  s->Printf("Try '%shelp' to see a current list of commands.\n",33            prefix.str().c_str());34  if (include_upropos) {35    s->Printf("Try '%sapropos %s' for a list of related commands.\n",36              prefix_str.c_str(), lookup_str.c_str());37  }38  if (include_type_lookup) {39    s->Printf("Try '%stype lookup %s' for information on types, methods, "40              "functions, modules, etc.",41              prefix_str.c_str(), lookup_str.c_str());42  }43}44 45CommandObjectHelp::CommandObjectHelp(CommandInterpreter &interpreter)46    : CommandObjectParsed(interpreter, "help",47                          "Show a list of all debugger "48                          "commands, or give details "49                          "about a specific command.",50                          "help [<cmd-name>]") {51  // A list of command names forming a path to the command we want help on.52  // No names is allowed - in which case we dump the top-level help.53  AddSimpleArgumentList(eArgTypeCommand, eArgRepeatStar);54}55 56CommandObjectHelp::~CommandObjectHelp() = default;57 58#define LLDB_OPTIONS_help59#include "CommandOptions.inc"60 61llvm::ArrayRef<OptionDefinition>62CommandObjectHelp::CommandOptions::GetDefinitions() {63  return llvm::ArrayRef(g_help_options);64}65 66void CommandObjectHelp::DoExecute(Args &command, CommandReturnObject &result) {67  CommandObject::CommandMap::iterator pos;68  CommandObject *cmd_obj;69  const size_t argc = command.GetArgumentCount();70 71  // 'help' doesn't take any arguments, other than command names.  If argc is72  // 0, we show the user all commands (aliases and user commands if asked for).73  // Otherwise every argument must be the name of a command or a sub-command.74  if (argc == 0) {75    uint32_t cmd_types = CommandInterpreter::eCommandTypesBuiltin;76    if (m_options.m_show_aliases)77      cmd_types |= CommandInterpreter::eCommandTypesAliases;78    if (m_options.m_show_user_defined) {79      cmd_types |= CommandInterpreter::eCommandTypesUserDef;80      cmd_types |= CommandInterpreter::eCommandTypesUserMW;81    }82    if (m_options.m_show_hidden)83      cmd_types |= CommandInterpreter::eCommandTypesHidden;84 85    result.SetStatus(eReturnStatusSuccessFinishNoResult);86    m_interpreter.GetHelp(result, cmd_types); // General help87  } else {88    // Get command object for the first command argument. Only search built-in89    // command dictionary.90    StringList matches;91    auto command_name = command[0].ref();92    cmd_obj = m_interpreter.GetCommandObject(command_name, &matches);93 94    if (cmd_obj != nullptr) {95      StringList matches;96      bool all_okay = true;97      CommandObject *sub_cmd_obj = cmd_obj;98      // Loop down through sub_command dictionaries until we find the command99      // object that corresponds to the help command entered.100      std::string sub_command;101      for (auto &entry : command.entries().drop_front()) {102        sub_command = std::string(entry.ref());103        matches.Clear();104        if (sub_cmd_obj->IsAlias())105          sub_cmd_obj =106              ((CommandAlias *)sub_cmd_obj)->GetUnderlyingCommand().get();107        if (!sub_cmd_obj->IsMultiwordObject()) {108          all_okay = false;109          break;110        } else {111          CommandObject *found_cmd;112          found_cmd =113              sub_cmd_obj->GetSubcommandObject(sub_command.c_str(), &matches);114          if (found_cmd == nullptr || matches.GetSize() > 1) {115            all_okay = false;116            break;117          } else118            sub_cmd_obj = found_cmd;119        }120      }121 122      if (!all_okay || (sub_cmd_obj == nullptr)) {123        std::string cmd_string;124        command.GetCommandString(cmd_string);125        if (matches.GetSize() >= 2) {126          StreamString s;127          s.Printf("ambiguous command %s", cmd_string.c_str());128          size_t num_matches = matches.GetSize();129          for (size_t match_idx = 0; match_idx < num_matches; match_idx++) {130            s.Printf("\n\t%s", matches.GetStringAtIndex(match_idx));131          }132          s.Printf("\n");133          result.AppendError(s.GetString());134          return;135        } else if (!sub_cmd_obj) {136          StreamString error_msg_stream;137          GenerateAdditionalHelpAvenuesMessage(138              &error_msg_stream, cmd_string.c_str(),139              m_interpreter.GetCommandPrefix(), sub_command.c_str());140          result.AppendError(error_msg_stream.GetString());141          return;142        } else {143          GenerateAdditionalHelpAvenuesMessage(144              &result.GetOutputStream(), cmd_string.c_str(),145              m_interpreter.GetCommandPrefix(), sub_command.c_str());146          result.GetOutputStream().Printf(147              "\nThe closest match is '%s'. Help on it follows.\n\n",148              sub_cmd_obj->GetCommandName().str().c_str());149        }150      }151 152      sub_cmd_obj->GenerateHelpText(result);153      std::string alias_full_name;154      // Don't use AliasExists here, that only checks exact name matches.  If155      // the user typed a shorter unique alias name, we should still tell them156      // it was an alias.157      if (m_interpreter.GetAliasFullName(command_name, alias_full_name)) {158        StreamString sstr;159        m_interpreter.GetAlias(alias_full_name)->GetAliasExpansion(sstr);160        result.GetOutputStream().Printf("\n'%s' is an abbreviation for %s\n",161                                        command[0].c_str(), sstr.GetData());162      }163    } else if (matches.GetSize() > 0) {164      Stream &output_strm = result.GetOutputStream();165      output_strm.Printf("Help requested with ambiguous command name, possible "166                         "completions:\n");167      const size_t match_count = matches.GetSize();168      for (size_t i = 0; i < match_count; i++) {169        output_strm.Printf("\t%s\n", matches.GetStringAtIndex(i));170      }171    } else {172      // Maybe the user is asking for help about a command argument rather than173      // a command.174      const CommandArgumentType arg_type =175          CommandObject::LookupArgumentName(command_name);176      if (arg_type != eArgTypeLastArg) {177        Stream &output_strm = result.GetOutputStream();178        CommandObject::GetArgumentHelp(output_strm, arg_type, m_interpreter);179        result.SetStatus(eReturnStatusSuccessFinishNoResult);180      } else {181        StreamString error_msg_stream;182        GenerateAdditionalHelpAvenuesMessage(&error_msg_stream, command_name,183                                             m_interpreter.GetCommandPrefix(),184                                             "");185        result.AppendError(error_msg_stream.GetString());186      }187    }188  }189}190 191void CommandObjectHelp::HandleCompletion(CompletionRequest &request) {192  // Return the completions of the commands in the help system:193  if (request.GetCursorIndex() == 0) {194    m_interpreter.HandleCompletionMatches(request);195    return;196  }197  CommandObject *cmd_obj =198      m_interpreter.GetCommandObject(request.GetParsedLine()[0].ref());199 200  // The command that they are getting help on might be ambiguous, in which201  // case we should complete that, otherwise complete with the command the202  // user is getting help on...203 204  if (cmd_obj) {205    request.ShiftArguments();206    cmd_obj->HandleCompletion(request);207    return;208  }209  m_interpreter.HandleCompletionMatches(request);210}211