LLDB mainline
CommandAlias.cpp
Go to the documentation of this file.
1//===-- CommandAlias.cpp --------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10
11#include "llvm/ADT/STLExtras.h"
12#include "llvm/Support/ErrorHandling.h"
13#include "llvm/Support/FormatAdapters.h"
14
20
21using namespace lldb;
22using namespace lldb_private;
23
24static llvm::Error
26 llvm::StringRef options_args,
27 OptionArgVectorSP &option_arg_vector_sp) {
28 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
29
30 if (options_args.size() < 1)
31 return llvm::Error::success();
32
33 Args args(options_args);
34 std::string options_string(options_args);
35 // Check to see if the command being aliased can take any command options.
36 Options *options = cmd_obj_sp->GetOptions();
37 if (options) {
38 // See if any options were specified as part of the alias; if so, handle
39 // them appropriately.
40 ExecutionContext exe_ctx =
41 cmd_obj_sp->GetCommandInterpreter().GetExecutionContext();
42 options->NotifyOptionParsingStarting(&exe_ctx);
43
44 llvm::Expected<Args> args_or =
45 options->ParseAlias(args, option_arg_vector, options_string);
46 if (!args_or)
47 return llvm::createStringError(
48 llvm::formatv("unable to create alias: {0}",
49 llvm::fmt_consume(args_or.takeError())));
50 args = std::move(*args_or);
51 if (llvm::Error error = options->VerifyPartialOptions())
52 return error;
53 }
54
55 if (!options_string.empty()) {
56 if (cmd_obj_sp->WantsRawCommandString()) {
57 option_arg_vector->emplace_back(CommandInterpreter::g_argument, -1,
58 options_string);
59 } else {
60 for (auto &entry : args.entries()) {
61 if (!entry.ref().empty())
62 option_arg_vector->emplace_back(
63 std::string(CommandInterpreter::g_argument), -1,
64 std::string(entry.ref()));
65 }
66 }
67 }
68
69 return llvm::Error::success();
70}
71
74 llvm::StringRef options_args, llvm::StringRef name,
75 llvm::StringRef help, llvm::StringRef syntax,
76 uint32_t flags)
77 : CommandObject(interpreter, name, help, syntax, flags),
78 m_option_string(std::string(options_args)),
81 m_did_set_help_long(false) {
82 if (llvm::Error error =
83 ProcessAliasOptionsArgs(cmd_sp, options_args, m_option_args_sp)) {
84 // FIXME: Find a way to percolate this error up.
86 "ProcessAliasOptionsArgs failed: {0}");
87 } else {
89 for (int i = 0;
90 auto *cmd_entry = m_underlying_command_sp->GetArgumentEntryAtIndex(i);
91 i++) {
92 m_arguments.push_back(*cmd_entry);
93 }
94 if (!help.empty()) {
95 StreamString sstr;
96 StreamString translation_and_help;
98
99 translation_and_help.Printf(
100 "(%s) %s", sstr.GetData(),
101 GetUnderlyingCommand()->GetHelp().str().c_str());
102 SetHelp(translation_and_help.GetString());
103 }
104 }
105}
106
108 if (IsValid())
109 return m_underlying_command_sp->WantsRawCommandString();
110 return false;
111}
112
114 if (IsValid())
115 return m_underlying_command_sp->WantsCompletion();
116 return false;
117}
118
120 if (IsValid())
121 m_underlying_command_sp->HandleCompletion(request);
122}
123
125 CompletionRequest &request, OptionElementVector &opt_element_vector) {
126 if (IsValid())
127 m_underlying_command_sp->HandleArgumentCompletion(request,
128 opt_element_vector);
129}
130
132 if (IsValid())
133 return m_underlying_command_sp->GetOptions();
134 return nullptr;
135}
136
137void CommandAlias::Execute(const char *args_string,
138 CommandReturnObject &result) {
139 llvm_unreachable("CommandAlias::Execute is not to be called");
140}
141
143 llvm::StringRef command_name = m_underlying_command_sp->GetCommandName();
144 help_string.Printf("'%*s", (int)command_name.size(), command_name.data());
145
146 if (!m_option_args_sp) {
147 help_string.Printf("'");
148 return;
149 }
150
151 OptionArgVector *options = m_option_args_sp.get();
152 std::string opt;
153 std::string value;
154
155 for (const auto &opt_entry : *options) {
156 std::tie(opt, std::ignore, value) = opt_entry;
158 help_string.Printf(" %s", value.c_str());
159 } else {
160 help_string.Printf(" %s", opt.c_str());
163 help_string.Printf(" %s", value.c_str());
164 }
165 }
166 }
167
168 help_string.Printf("'");
169}
170
175 if (!IsValid())
176 return false;
177
178 std::string opt;
179 std::string value;
180
181 for (const auto &opt_entry : *GetOptionArguments()) {
182 std::tie(opt, std::ignore, value) = opt_entry;
183 if (opt == CommandInterpreter::g_argument && !value.empty() &&
184 llvm::StringRef(value).ends_with("--")) {
186 break;
187 }
188 }
189
190 // if this is a nested alias, it may be adding arguments on top of an already
191 // dash-dash alias
194 (GetUnderlyingCommand()->IsDashDashCommand() ? eLazyBoolYes
195 : eLazyBoolNo);
197}
198
201 return GetUnderlyingCommand()->IsAlias();
202 return false;
203}
204
205std::pair<lldb::CommandObjectSP, OptionArgVectorSP> CommandAlias::Desugar() {
206 auto underlying = GetUnderlyingCommand();
207 if (!underlying)
208 return {nullptr, nullptr};
209
210 if (underlying->IsAlias()) {
211 // FIXME: This doesn't work if the original alias fills a slot in the
212 // underlying alias, since this just appends the two lists.
213 auto desugared = ((CommandAlias *)underlying.get())->Desugar();
214 OptionArgVectorSP options = std::make_shared<OptionArgVector>();
215 llvm::append_range(*options, *desugared.second);
216 llvm::append_range(*options, *GetOptionArguments());
217 return {desugared.first, options};
218 }
219
220 return {underlying, GetOptionArguments()};
221}
222
223// allow CommandAlias objects to provide their own help, but fallback to the
224// info for the underlying command if no customization has been provided
225void CommandAlias::SetHelp(llvm::StringRef str) {
226 this->CommandObject::SetHelp(str);
227 m_did_set_help = true;
228}
229
230void CommandAlias::SetHelpLong(llvm::StringRef str) {
232 m_did_set_help_long = true;
233}
234
235llvm::StringRef CommandAlias::GetHelp() {
236 if (!m_cmd_help_short.empty() || m_did_set_help)
237 return m_cmd_help_short;
238 if (IsValid())
239 return m_underlying_command_sp->GetHelp();
240 return llvm::StringRef();
241}
242
243llvm::StringRef CommandAlias::GetHelpLong() {
244 if (!m_cmd_help_long.empty() || m_did_set_help_long)
245 return m_cmd_help_long;
246 if (IsValid())
247 return m_underlying_command_sp->GetHelpLong();
248 return llvm::StringRef();
249}
static llvm::Error ProcessAliasOptionsArgs(lldb::CommandObjectSP &cmd_obj_sp, llvm::StringRef options_args, OptionArgVectorSP &option_arg_vector_sp)
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOG_ERROR(log, error,...)
Definition Log.h:392
A command line argument class.
Definition Args.h:33
llvm::ArrayRef< ArgEntry > entries() const
Definition Args.h:132
lldb::CommandObjectSP GetUnderlyingCommand()
llvm::StringRef GetHelpLong() override
void HandleCompletion(CompletionRequest &request) override
This default version handles calling option argument completions and then calls HandleArgumentComplet...
void Execute(const char *args_string, CommandReturnObject &result) override
OptionArgVectorSP GetOptionArguments() const
bool WantsCompletion() override
OptionArgVectorSP m_option_args_sp
Options * GetOptions() override
void SetHelp(llvm::StringRef str) override
bool WantsRawCommandString() override
void GetAliasExpansion(StreamString &help_string) const
void SetHelpLong(llvm::StringRef str) override
std::pair< lldb::CommandObjectSP, OptionArgVectorSP > Desugar()
void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override
The default version handles argument definitions that have only one argument type,...
CommandAlias(CommandInterpreter &interpreter, lldb::CommandObjectSP cmd_sp, llvm::StringRef options_args, llvm::StringRef name, llvm::StringRef help=llvm::StringRef(), llvm::StringRef syntax=llvm::StringRef(), uint32_t flags=0)
lldb::CommandObjectSP m_underlying_command_sp
llvm::StringRef GetHelp() override
bool IsDashDashCommand() override
virtual void SetHelpLong(llvm::StringRef str)
std::vector< CommandArgumentEntry > m_arguments
CommandObject(CommandInterpreter &interpreter, llvm::StringRef name, llvm::StringRef help="", llvm::StringRef syntax="", uint32_t flags=0)
virtual void SetHelp(llvm::StringRef str)
"lldb/Utility/ArgCompletionRequest.h"
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
A command line option parsing protocol class.
Definition Options.h:58
llvm::Error VerifyPartialOptions()
Definition Options.cpp:601
void NotifyOptionParsingStarting(ExecutionContext *execution_context)
Definition Options.cpp:69
llvm::Expected< Args > ParseAlias(const Args &args, OptionArgVector *option_arg_vector, std::string &input_line)
Definition Options.cpp:975
const char * GetData() const
llvm::StringRef GetString() const
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition Stream.cpp:134
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition Log.h:332
std::vector< OptionArgElement > OptionElementVector
Definition Options.h:43
std::shared_ptr< OptionArgVector > OptionArgVectorSP
Definition Options.h:30
std::vector< std::tuple< std::string, int, std::string > > OptionArgVector
Definition Options.h:29
std::shared_ptr< lldb_private::CommandObject > CommandObjectSP