Files
llvm/lldb/source/API/SBCommandInterpreter.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

868 lines
35 KiB
C++
Raw Normal View History

//===-- SBCommandInterpreter.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 "lldb/lldb-types.h"
#include "SBReproducerPrivate.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/Listener.h"
#include "lldb/API/SBBroadcaster.h"
#include "lldb/API/SBCommandInterpreter.h"
#include "lldb/API/SBCommandInterpreterRunOptions.h"
#include "lldb/API/SBCommandReturnObject.h"
Fix handling of CommandInterpreter's events in lldb-mi Summary: Previously lldb-mi contains a stub for that but it didn't work and all CommanInterpreter's events were ignored. This commit adds a handling of CommandInterpreter's events in lldb-mi. Steps: # Fix CMICmnLLDBDebugger::InitSBListener # Add SBCommandInterpreter::EventIsCommandInterpreterEvent # Exit on lldb::SBCommandInterpreter::eBroadcastBitQuitCommandReceived All tests pass on OS X. In further we can remove "quit" hack in lldb-mi. Test Plan: # Create start_script file: ``` target create ~/p/hello b main r quit ``` # Run lldb-mi --interpreter # Execute start_script file by following command: ``` -interpreter-exec console "command source start_script" ``` Log: ``` $ bin/lldb-mi --interpreter (gdb) -interpreter-exec console "command source start_script" Executing commands in '/Users/IliaK/p/llvm/build_ninja/start_script'. (lldb) target create ~/p/hello Current executable set to '~/p/hello' (x86_64). (lldb) b main Breakpoint 1: where = hello`main + 29 at hello.cpp:12, address = 0x0000000100000e2d (lldb) r Process 1582 launched: '/Users/IliaK/p/hello' (x86_64) (lldb) quit ^done (gdb) =thread-created,id="1",group-id="i1" =thread-selected,id="1" (gdb) =shlibs-added,shlib-info=[num="1",name="hello",dyld-addr="-",reason="dyld",path="/Users/IliaK/p/hello",loaded_addr="-",dsym-objpath="/Users/IliaK/p/hello.dSYM/Contents/Resources/DWARF/hello"] ... =shlibs-added,shlib-info=[num="132",name="libDiagnosticMessagesClient.dylib",dyld-addr="0x7fff91705000",reason="dyld",path="/usr/lib/libDiagnosticMessagesClient.dylib",loaded_addr="0x7fff91705000"] (gdb) *stopped,reason="breakpoint-hit",disp="del",bkptno="1",frame={addr="0x100000e2d",func="main",args=[{name="argc",value="1"},{name="argv",value="0x00007fff5fbffc88"}],file="hello.cpp",fullname="/Users/IliaK/p/hello.cpp",line="12"},thread-id="1",stopped-threads="all" (gdb)<press Enter> MI: Program exited OK ``` Reviewers: abidh, clayborg Reviewed By: abidh Subscribers: jingham, lldb-commits, clayborg, abidh Differential Revision: http://reviews.llvm.org/D8382 llvm-svn: 232891
2015-03-21 10:53:37 +00:00
#include "lldb/API/SBEvent.h"
#include "lldb/API/SBExecutionContext.h"
#include "lldb/API/SBListener.h"
#include "lldb/API/SBProcess.h"
#include "lldb/API/SBStream.h"
#include "lldb/API/SBStringList.h"
#include "lldb/API/SBTarget.h"
#include <memory>
using namespace lldb;
using namespace lldb_private;
class CommandPluginInterfaceImplementation : public CommandObjectParsed {
public:
CommandPluginInterfaceImplementation(CommandInterpreter &interpreter,
const char *name,
lldb::SBCommandPluginInterface *backend,
const char *help = nullptr,
const char *syntax = nullptr,
uint32_t flags = 0,
const char *auto_repeat_command = "")
: CommandObjectParsed(interpreter, name, help, syntax, flags),
m_backend(backend) {
m_auto_repeat_command =
auto_repeat_command == nullptr
? llvm::None
: llvm::Optional<std::string>(auto_repeat_command);
}
bool IsRemovable() const override { return true; }
/// More documentation is available in lldb::CommandObject::GetRepeatCommand,
/// but in short, if nullptr is returned, the previous command will be
/// repeated, and if an empty string is returned, no commands will be
/// executed.
const char *GetRepeatCommand(Args &current_command_args,
uint32_t index) override {
if (!m_auto_repeat_command)
return nullptr;
else
return m_auto_repeat_command->c_str();
}
protected:
bool DoExecute(Args &command, CommandReturnObject &result) override {
SBCommandReturnObject sb_return(result);
SBCommandInterpreter sb_interpreter(&m_interpreter);
SBDebugger debugger_sb(m_interpreter.GetDebugger().shared_from_this());
bool ret = m_backend->DoExecute(
debugger_sb, command.GetArgumentVector(), sb_return);
return ret;
}
std::shared_ptr<lldb::SBCommandPluginInterface> m_backend;
llvm::Optional<std::string> m_auto_repeat_command;
};
SBCommandInterpreter::SBCommandInterpreter(CommandInterpreter *interpreter)
: m_opaque_ptr(interpreter) {
LLDB_RECORD_CONSTRUCTOR(SBCommandInterpreter,
(lldb_private::CommandInterpreter *), interpreter);
}
SBCommandInterpreter::SBCommandInterpreter(const SBCommandInterpreter &rhs)
: m_opaque_ptr(rhs.m_opaque_ptr) {
LLDB_RECORD_CONSTRUCTOR(SBCommandInterpreter,
(const lldb::SBCommandInterpreter &), rhs);
}
SBCommandInterpreter::~SBCommandInterpreter() = default;
const SBCommandInterpreter &SBCommandInterpreter::
operator=(const SBCommandInterpreter &rhs) {
LLDB_RECORD_METHOD(
const lldb::SBCommandInterpreter &,
SBCommandInterpreter, operator=,(const lldb::SBCommandInterpreter &),
rhs);
m_opaque_ptr = rhs.m_opaque_ptr;
return LLDB_RECORD_RESULT(*this);
}
bool SBCommandInterpreter::IsValid() const {
LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBCommandInterpreter, IsValid);
return this->operator bool();
}
SBCommandInterpreter::operator bool() const {
LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBCommandInterpreter, operator bool);
return m_opaque_ptr != nullptr;
}
bool SBCommandInterpreter::CommandExists(const char *cmd) {
LLDB_RECORD_METHOD(bool, SBCommandInterpreter, CommandExists, (const char *),
cmd);
return (((cmd != nullptr) && IsValid()) ? m_opaque_ptr->CommandExists(cmd)
: false);
}
bool SBCommandInterpreter::AliasExists(const char *cmd) {
LLDB_RECORD_METHOD(bool, SBCommandInterpreter, AliasExists, (const char *),
cmd);
return (((cmd != nullptr) && IsValid()) ? m_opaque_ptr->AliasExists(cmd)
: false);
}
bool SBCommandInterpreter::IsActive() {
LLDB_RECORD_METHOD_NO_ARGS(bool, SBCommandInterpreter, IsActive);
return (IsValid() ? m_opaque_ptr->IsActive() : false);
}
bool SBCommandInterpreter::WasInterrupted() const {
LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBCommandInterpreter, WasInterrupted);
return (IsValid() ? m_opaque_ptr->WasInterrupted() : false);
}
const char *SBCommandInterpreter::GetIOHandlerControlSequence(char ch) {
LLDB_RECORD_METHOD(const char *, SBCommandInterpreter,
GetIOHandlerControlSequence, (char), ch);
return (IsValid()
? m_opaque_ptr->GetDebugger()
.GetTopIOHandlerControlSequence(ch)
.GetCString()
: nullptr);
}
lldb::ReturnStatus
SBCommandInterpreter::HandleCommand(const char *command_line,
SBCommandReturnObject &result,
bool add_to_history) {
LLDB_RECORD_METHOD(lldb::ReturnStatus, SBCommandInterpreter, HandleCommand,
(const char *, lldb::SBCommandReturnObject &, bool),
command_line, result, add_to_history);
SBExecutionContext sb_exe_ctx;
return HandleCommand(command_line, sb_exe_ctx, result, add_to_history);
}
lldb::ReturnStatus SBCommandInterpreter::HandleCommand(
const char *command_line, SBExecutionContext &override_context,
SBCommandReturnObject &result, bool add_to_history) {
LLDB_RECORD_METHOD(lldb::ReturnStatus, SBCommandInterpreter, HandleCommand,
(const char *, lldb::SBExecutionContext &,
lldb::SBCommandReturnObject &, bool),
command_line, override_context, result, add_to_history);
result.Clear();
if (command_line && IsValid()) {
result.ref().SetInteractive(false);
auto do_add_to_history = add_to_history ? eLazyBoolYes : eLazyBoolNo;
if (override_context.get())
m_opaque_ptr->HandleCommand(command_line, do_add_to_history,
override_context.get()->Lock(true),
result.ref());
else
m_opaque_ptr->HandleCommand(command_line, do_add_to_history,
result.ref());
} else {
result->AppendError(
"SBCommandInterpreter or the command line is not valid");
}
return result.GetStatus();
}
void SBCommandInterpreter::HandleCommandsFromFile(
lldb::SBFileSpec &file, lldb::SBExecutionContext &override_context,
lldb::SBCommandInterpreterRunOptions &options,
lldb::SBCommandReturnObject result) {
LLDB_RECORD_METHOD(void, SBCommandInterpreter, HandleCommandsFromFile,
(lldb::SBFileSpec &, lldb::SBExecutionContext &,
lldb::SBCommandInterpreterRunOptions &,
lldb::SBCommandReturnObject),
file, override_context, options, result);
if (!IsValid()) {
result->AppendError("SBCommandInterpreter is not valid.");
return;
}
if (!file.IsValid()) {
SBStream s;
file.GetDescription(s);
result->AppendErrorWithFormat("File is not valid: %s.", s.GetData());
}
FileSpec tmp_spec = file.ref();
if (override_context.get())
m_opaque_ptr->HandleCommandsFromFile(tmp_spec,
override_context.get()->Lock(true),
options.ref(),
result.ref());
else
m_opaque_ptr->HandleCommandsFromFile(tmp_spec, options.ref(), result.ref());
}
int SBCommandInterpreter::HandleCompletion(
const char *current_line, const char *cursor, const char *last_char,
int match_start_point, int max_return_elements, SBStringList &matches) {
LLDB_RECORD_METHOD(int, SBCommandInterpreter, HandleCompletion,
(const char *, const char *, const char *, int, int,
lldb::SBStringList &),
current_line, cursor, last_char, match_start_point,
max_return_elements, matches);
Add support for descriptions with command completions. Summary: This patch adds a framework for adding descriptions to the command completions we provide. It also adds descriptions for completed top-level commands so that we can test this code. Completions are in general supposed to be displayed alongside the completion itself. The descriptions can be used to provide additional information about the completion to the user. Examples for descriptions are function signatures when completing function calls in the expression command or the binary name when providing completion for a symbol. There is still some boilerplate code from the old completion API left in LLDB (mostly because the respective APIs are reused for non-completion related purposes, so the CompletionRequest doesn't make sense to be used), so that's why I still had to change some function signatures. Also, as the old API only passes around a list of matches, and the descriptions are for these functions just another list, I had to add some code that essentially just ensures that both lists are always the same side (e.g. all the manual calls to `descriptions->AddString(X)` below a `matches->AddString(Y)` call). The initial command descriptions that come with this patch are just reusing the existing short help that is already added in LLDB. An example completion with descriptions looks like this: ``` (lldb) pl Available completions: platform -- Commands to manage and create platforms. plugin -- Commands for managing LLDB plugins. ``` Reviewers: #lldb, jingham Reviewed By: #lldb, jingham Subscribers: jingham, JDevlieghere, lldb-commits Differential Revision: https://reviews.llvm.org/D51175 llvm-svn: 342181
2018-09-13 21:26:00 +00:00
SBStringList dummy_descriptions;
return HandleCompletionWithDescriptions(
current_line, cursor, last_char, match_start_point, max_return_elements,
matches, dummy_descriptions);
}
int SBCommandInterpreter::HandleCompletionWithDescriptions(
const char *current_line, const char *cursor, const char *last_char,
int match_start_point, int max_return_elements, SBStringList &matches,
SBStringList &descriptions) {
LLDB_RECORD_METHOD(int, SBCommandInterpreter,
HandleCompletionWithDescriptions,
(const char *, const char *, const char *, int, int,
lldb::SBStringList &, lldb::SBStringList &),
current_line, cursor, last_char, match_start_point,
max_return_elements, matches, descriptions);
// Sanity check the arguments that are passed in: cursor & last_char have to
// be within the current_line.
if (current_line == nullptr || cursor == nullptr || last_char == nullptr)
return 0;
if (cursor < current_line || last_char < current_line)
return 0;
size_t current_line_size = strlen(current_line);
if (cursor - current_line > static_cast<ptrdiff_t>(current_line_size) ||
last_char - current_line > static_cast<ptrdiff_t>(current_line_size))
return 0;
[lldb][NFC] Remove WordComplete mode, make result array indexed from 0 and remove any undocumented/redundant return values Summary: We still have some leftovers of the old completion API in the internals of LLDB that haven't been replaced by the new CompletionRequest. These leftovers are: * The return values (int/size_t) in all completion functions. * Our result array that starts indexing at 1. * `WordComplete` mode. I didn't replace them back then because it's tricky to figure out what exactly they are used for and the completion code is relatively untested. I finally got around to writing more tests for the API and understanding the semantics, so I think it's a good time to get rid of them. A few words why those things should be removed/replaced: * The return values are really cryptic, partly redundant and rarely documented. They are also completely ignored by Xcode, so whatever information they contain will end up breaking Xcode's completion mechanism. They are also partly impossible to even implement as we assign negative values special meaning and our completion API sometimes returns size_t. Completion functions are supposed to return -2 to rewrite the current line. We seem to use this in some untested code path to expand the history repeat character to the full command, but I haven't figured out why that doesn't work at the moment. Completion functions return -1 to 'insert the completion character', but that isn't implemented (even though we seem to activate this feature in LLDB sometimes). All positive values have to match the number of results. This is obviously just redundant information as the user can just look at the result list to get that information (which is what Xcode does). * The result array that starts indexing at 1 is obviously unexpected. The first element of the array is reserved for the common prefix of all completions (e.g. "foobar" and "footar" -> "foo"). The idea is that we calculate this to make the life of the API caller easier, but obviously forcing people to have 1-based indices is not helpful (or even worse, forces them to manually copy the results to make it 0-based like Xcode has to do). * The `WordComplete` mode indicates that LLDB should enter a space behind the completion. The idea is that we let the top-level API know that we just provided a full completion. Interestingly we `WordComplete` is just a single bool that somehow represents all N completions. And we always provide full completions in LLDB, so in theory it should always be true. The only use it currently serves is providing redundant information about whether we have a single definitive completion or not (which we already know from the number of results we get). This patch essentially removes `WordComplete` mode and makes the result array indexed from 0. It also removes all return values from all internal completion functions. The only non-redundant information they contain is about rewriting the current line (which is broken), so that functionality was moved to the CompletionRequest API. So you can now do `addCompletion("blub", "description", CompletionMode::RewriteLine)` to do the same. For the SB API we emulate the old behaviour by making the array indexed from 1 again with the common prefix at index 0. I didn't keep the special negative return codes as we either never sent them before (e.g. -2) or we didn't even implement them in the Editline handler (e.g. -1). I tried to keep this patch minimal and I'm aware we can probably now even further simplify a bunch of related code, but I would prefer doing this in follow-up NFC commits Reviewers: JDevlieghere Reviewed By: JDevlieghere Subscribers: arphaman, abidh, lldb-commits Tags: #lldb Differential Revision: https://reviews.llvm.org/D66536 llvm-svn: 369624
2019-08-22 07:41:23 +00:00
if (!IsValid())
return 0;
[lldb][NFC] Remove WordComplete mode, make result array indexed from 0 and remove any undocumented/redundant return values Summary: We still have some leftovers of the old completion API in the internals of LLDB that haven't been replaced by the new CompletionRequest. These leftovers are: * The return values (int/size_t) in all completion functions. * Our result array that starts indexing at 1. * `WordComplete` mode. I didn't replace them back then because it's tricky to figure out what exactly they are used for and the completion code is relatively untested. I finally got around to writing more tests for the API and understanding the semantics, so I think it's a good time to get rid of them. A few words why those things should be removed/replaced: * The return values are really cryptic, partly redundant and rarely documented. They are also completely ignored by Xcode, so whatever information they contain will end up breaking Xcode's completion mechanism. They are also partly impossible to even implement as we assign negative values special meaning and our completion API sometimes returns size_t. Completion functions are supposed to return -2 to rewrite the current line. We seem to use this in some untested code path to expand the history repeat character to the full command, but I haven't figured out why that doesn't work at the moment. Completion functions return -1 to 'insert the completion character', but that isn't implemented (even though we seem to activate this feature in LLDB sometimes). All positive values have to match the number of results. This is obviously just redundant information as the user can just look at the result list to get that information (which is what Xcode does). * The result array that starts indexing at 1 is obviously unexpected. The first element of the array is reserved for the common prefix of all completions (e.g. "foobar" and "footar" -> "foo"). The idea is that we calculate this to make the life of the API caller easier, but obviously forcing people to have 1-based indices is not helpful (or even worse, forces them to manually copy the results to make it 0-based like Xcode has to do). * The `WordComplete` mode indicates that LLDB should enter a space behind the completion. The idea is that we let the top-level API know that we just provided a full completion. Interestingly we `WordComplete` is just a single bool that somehow represents all N completions. And we always provide full completions in LLDB, so in theory it should always be true. The only use it currently serves is providing redundant information about whether we have a single definitive completion or not (which we already know from the number of results we get). This patch essentially removes `WordComplete` mode and makes the result array indexed from 0. It also removes all return values from all internal completion functions. The only non-redundant information they contain is about rewriting the current line (which is broken), so that functionality was moved to the CompletionRequest API. So you can now do `addCompletion("blub", "description", CompletionMode::RewriteLine)` to do the same. For the SB API we emulate the old behaviour by making the array indexed from 1 again with the common prefix at index 0. I didn't keep the special negative return codes as we either never sent them before (e.g. -2) or we didn't even implement them in the Editline handler (e.g. -1). I tried to keep this patch minimal and I'm aware we can probably now even further simplify a bunch of related code, but I would prefer doing this in follow-up NFC commits Reviewers: JDevlieghere Reviewed By: JDevlieghere Subscribers: arphaman, abidh, lldb-commits Tags: #lldb Differential Revision: https://reviews.llvm.org/D66536 llvm-svn: 369624
2019-08-22 07:41:23 +00:00
lldb_private::StringList lldb_matches, lldb_descriptions;
CompletionResult result;
CompletionRequest request(current_line, cursor - current_line, result);
m_opaque_ptr->HandleCompletion(request);
result.GetMatches(lldb_matches);
result.GetDescriptions(lldb_descriptions);
// Make the result array indexed from 1 again by adding the 'common prefix'
// of all completions as element 0. This is done to emulate the old API.
if (request.GetParsedLine().GetArgumentCount() == 0) {
// If we got an empty string, insert nothing.
lldb_matches.InsertStringAtIndex(0, "");
lldb_descriptions.InsertStringAtIndex(0, "");
} else {
// Now figure out if there is a common substring, and if so put that in
// element 0, otherwise put an empty string in element 0.
std::string command_partial_str = request.GetCursorArgumentPrefix().str();
std::string common_prefix = lldb_matches.LongestCommonPrefix();
const size_t partial_name_len = command_partial_str.size();
common_prefix.erase(0, partial_name_len);
// If we matched a unique single command, add a space... Only do this if
// the completer told us this was a complete word, however...
if (lldb_matches.GetSize() == 1) {
char quote_char = request.GetParsedArg().GetQuoteChar();
[lldb][NFC] Remove WordComplete mode, make result array indexed from 0 and remove any undocumented/redundant return values Summary: We still have some leftovers of the old completion API in the internals of LLDB that haven't been replaced by the new CompletionRequest. These leftovers are: * The return values (int/size_t) in all completion functions. * Our result array that starts indexing at 1. * `WordComplete` mode. I didn't replace them back then because it's tricky to figure out what exactly they are used for and the completion code is relatively untested. I finally got around to writing more tests for the API and understanding the semantics, so I think it's a good time to get rid of them. A few words why those things should be removed/replaced: * The return values are really cryptic, partly redundant and rarely documented. They are also completely ignored by Xcode, so whatever information they contain will end up breaking Xcode's completion mechanism. They are also partly impossible to even implement as we assign negative values special meaning and our completion API sometimes returns size_t. Completion functions are supposed to return -2 to rewrite the current line. We seem to use this in some untested code path to expand the history repeat character to the full command, but I haven't figured out why that doesn't work at the moment. Completion functions return -1 to 'insert the completion character', but that isn't implemented (even though we seem to activate this feature in LLDB sometimes). All positive values have to match the number of results. This is obviously just redundant information as the user can just look at the result list to get that information (which is what Xcode does). * The result array that starts indexing at 1 is obviously unexpected. The first element of the array is reserved for the common prefix of all completions (e.g. "foobar" and "footar" -> "foo"). The idea is that we calculate this to make the life of the API caller easier, but obviously forcing people to have 1-based indices is not helpful (or even worse, forces them to manually copy the results to make it 0-based like Xcode has to do). * The `WordComplete` mode indicates that LLDB should enter a space behind the completion. The idea is that we let the top-level API know that we just provided a full completion. Interestingly we `WordComplete` is just a single bool that somehow represents all N completions. And we always provide full completions in LLDB, so in theory it should always be true. The only use it currently serves is providing redundant information about whether we have a single definitive completion or not (which we already know from the number of results we get). This patch essentially removes `WordComplete` mode and makes the result array indexed from 0. It also removes all return values from all internal completion functions. The only non-redundant information they contain is about rewriting the current line (which is broken), so that functionality was moved to the CompletionRequest API. So you can now do `addCompletion("blub", "description", CompletionMode::RewriteLine)` to do the same. For the SB API we emulate the old behaviour by making the array indexed from 1 again with the common prefix at index 0. I didn't keep the special negative return codes as we either never sent them before (e.g. -2) or we didn't even implement them in the Editline handler (e.g. -1). I tried to keep this patch minimal and I'm aware we can probably now even further simplify a bunch of related code, but I would prefer doing this in follow-up NFC commits Reviewers: JDevlieghere Reviewed By: JDevlieghere Subscribers: arphaman, abidh, lldb-commits Tags: #lldb Differential Revision: https://reviews.llvm.org/D66536 llvm-svn: 369624
2019-08-22 07:41:23 +00:00
common_prefix =
Args::EscapeLLDBCommandArgument(common_prefix, quote_char);
if (request.GetParsedArg().IsQuoted())
common_prefix.push_back(quote_char);
common_prefix.push_back(' ');
}
lldb_matches.InsertStringAtIndex(0, common_prefix.c_str());
lldb_descriptions.InsertStringAtIndex(0, "");
}
[lldb][NFC] Remove WordComplete mode, make result array indexed from 0 and remove any undocumented/redundant return values Summary: We still have some leftovers of the old completion API in the internals of LLDB that haven't been replaced by the new CompletionRequest. These leftovers are: * The return values (int/size_t) in all completion functions. * Our result array that starts indexing at 1. * `WordComplete` mode. I didn't replace them back then because it's tricky to figure out what exactly they are used for and the completion code is relatively untested. I finally got around to writing more tests for the API and understanding the semantics, so I think it's a good time to get rid of them. A few words why those things should be removed/replaced: * The return values are really cryptic, partly redundant and rarely documented. They are also completely ignored by Xcode, so whatever information they contain will end up breaking Xcode's completion mechanism. They are also partly impossible to even implement as we assign negative values special meaning and our completion API sometimes returns size_t. Completion functions are supposed to return -2 to rewrite the current line. We seem to use this in some untested code path to expand the history repeat character to the full command, but I haven't figured out why that doesn't work at the moment. Completion functions return -1 to 'insert the completion character', but that isn't implemented (even though we seem to activate this feature in LLDB sometimes). All positive values have to match the number of results. This is obviously just redundant information as the user can just look at the result list to get that information (which is what Xcode does). * The result array that starts indexing at 1 is obviously unexpected. The first element of the array is reserved for the common prefix of all completions (e.g. "foobar" and "footar" -> "foo"). The idea is that we calculate this to make the life of the API caller easier, but obviously forcing people to have 1-based indices is not helpful (or even worse, forces them to manually copy the results to make it 0-based like Xcode has to do). * The `WordComplete` mode indicates that LLDB should enter a space behind the completion. The idea is that we let the top-level API know that we just provided a full completion. Interestingly we `WordComplete` is just a single bool that somehow represents all N completions. And we always provide full completions in LLDB, so in theory it should always be true. The only use it currently serves is providing redundant information about whether we have a single definitive completion or not (which we already know from the number of results we get). This patch essentially removes `WordComplete` mode and makes the result array indexed from 0. It also removes all return values from all internal completion functions. The only non-redundant information they contain is about rewriting the current line (which is broken), so that functionality was moved to the CompletionRequest API. So you can now do `addCompletion("blub", "description", CompletionMode::RewriteLine)` to do the same. For the SB API we emulate the old behaviour by making the array indexed from 1 again with the common prefix at index 0. I didn't keep the special negative return codes as we either never sent them before (e.g. -2) or we didn't even implement them in the Editline handler (e.g. -1). I tried to keep this patch minimal and I'm aware we can probably now even further simplify a bunch of related code, but I would prefer doing this in follow-up NFC commits Reviewers: JDevlieghere Reviewed By: JDevlieghere Subscribers: arphaman, abidh, lldb-commits Tags: #lldb Differential Revision: https://reviews.llvm.org/D66536 llvm-svn: 369624
2019-08-22 07:41:23 +00:00
SBStringList temp_matches_list(&lldb_matches);
matches.AppendList(temp_matches_list);
SBStringList temp_descriptions_list(&lldb_descriptions);
descriptions.AppendList(temp_descriptions_list);
return result.GetNumberOfResults();
}
Add support for descriptions with command completions. Summary: This patch adds a framework for adding descriptions to the command completions we provide. It also adds descriptions for completed top-level commands so that we can test this code. Completions are in general supposed to be displayed alongside the completion itself. The descriptions can be used to provide additional information about the completion to the user. Examples for descriptions are function signatures when completing function calls in the expression command or the binary name when providing completion for a symbol. There is still some boilerplate code from the old completion API left in LLDB (mostly because the respective APIs are reused for non-completion related purposes, so the CompletionRequest doesn't make sense to be used), so that's why I still had to change some function signatures. Also, as the old API only passes around a list of matches, and the descriptions are for these functions just another list, I had to add some code that essentially just ensures that both lists are always the same side (e.g. all the manual calls to `descriptions->AddString(X)` below a `matches->AddString(Y)` call). The initial command descriptions that come with this patch are just reusing the existing short help that is already added in LLDB. An example completion with descriptions looks like this: ``` (lldb) pl Available completions: platform -- Commands to manage and create platforms. plugin -- Commands for managing LLDB plugins. ``` Reviewers: #lldb, jingham Reviewed By: #lldb, jingham Subscribers: jingham, JDevlieghere, lldb-commits Differential Revision: https://reviews.llvm.org/D51175 llvm-svn: 342181
2018-09-13 21:26:00 +00:00
int SBCommandInterpreter::HandleCompletionWithDescriptions(
const char *current_line, uint32_t cursor_pos, int match_start_point,
int max_return_elements, SBStringList &matches,
SBStringList &descriptions) {
LLDB_RECORD_METHOD(int, SBCommandInterpreter,
HandleCompletionWithDescriptions,
(const char *, uint32_t, int, int, lldb::SBStringList &,
lldb::SBStringList &),
current_line, cursor_pos, match_start_point,
max_return_elements, matches, descriptions);
Add support for descriptions with command completions. Summary: This patch adds a framework for adding descriptions to the command completions we provide. It also adds descriptions for completed top-level commands so that we can test this code. Completions are in general supposed to be displayed alongside the completion itself. The descriptions can be used to provide additional information about the completion to the user. Examples for descriptions are function signatures when completing function calls in the expression command or the binary name when providing completion for a symbol. There is still some boilerplate code from the old completion API left in LLDB (mostly because the respective APIs are reused for non-completion related purposes, so the CompletionRequest doesn't make sense to be used), so that's why I still had to change some function signatures. Also, as the old API only passes around a list of matches, and the descriptions are for these functions just another list, I had to add some code that essentially just ensures that both lists are always the same side (e.g. all the manual calls to `descriptions->AddString(X)` below a `matches->AddString(Y)` call). The initial command descriptions that come with this patch are just reusing the existing short help that is already added in LLDB. An example completion with descriptions looks like this: ``` (lldb) pl Available completions: platform -- Commands to manage and create platforms. plugin -- Commands for managing LLDB plugins. ``` Reviewers: #lldb, jingham Reviewed By: #lldb, jingham Subscribers: jingham, JDevlieghere, lldb-commits Differential Revision: https://reviews.llvm.org/D51175 llvm-svn: 342181
2018-09-13 21:26:00 +00:00
const char *cursor = current_line + cursor_pos;
const char *last_char = current_line + strlen(current_line);
return HandleCompletionWithDescriptions(
current_line, cursor, last_char, match_start_point, max_return_elements,
matches, descriptions);
}
int SBCommandInterpreter::HandleCompletion(const char *current_line,
uint32_t cursor_pos,
int match_start_point,
int max_return_elements,
lldb::SBStringList &matches) {
LLDB_RECORD_METHOD(int, SBCommandInterpreter, HandleCompletion,
(const char *, uint32_t, int, int, lldb::SBStringList &),
current_line, cursor_pos, match_start_point,
max_return_elements, matches);
const char *cursor = current_line + cursor_pos;
const char *last_char = current_line + strlen(current_line);
return HandleCompletion(current_line, cursor, last_char, match_start_point,
max_return_elements, matches);
}
bool SBCommandInterpreter::HasCommands() {
LLDB_RECORD_METHOD_NO_ARGS(bool, SBCommandInterpreter, HasCommands);
return (IsValid() ? m_opaque_ptr->HasCommands() : false);
}
bool SBCommandInterpreter::HasAliases() {
LLDB_RECORD_METHOD_NO_ARGS(bool, SBCommandInterpreter, HasAliases);
return (IsValid() ? m_opaque_ptr->HasAliases() : false);
}
bool SBCommandInterpreter::HasAliasOptions() {
LLDB_RECORD_METHOD_NO_ARGS(bool, SBCommandInterpreter, HasAliasOptions);
return (IsValid() ? m_opaque_ptr->HasAliasOptions() : false);
}
2010-10-30 04:51:46 +00:00
SBProcess SBCommandInterpreter::GetProcess() {
LLDB_RECORD_METHOD_NO_ARGS(lldb::SBProcess, SBCommandInterpreter, GetProcess);
SBFrame is now threadsafe using some extra tricks. One issue is that stack frames might go away (the object itself, not the actual logical frame) when we are single stepping due to the way we currently sometimes end up flushing frames when stepping in/out/over. They later will come back to life represented by another object yet they have the same StackID. Now when you get a lldb::SBFrame object, it will track the frame it is initialized with until the thread goes away or the StackID no longer exists in the stack for the thread it was created on. It uses a weak_ptr to both the frame and thread and also stores the StackID. These three items allow us to determine when the stack frame object has gone away (the weak_ptr will be NULL) and allows us to find the correct frame again. In our test suite we had such cases where we were just getting lucky when something like this happened: 1 - stop at breakpoint 2 - get first frame in thread where we stopped 3 - run an expression that causes the program to JIT and run code 4 - run more expressions on the frame from step 2 which was very very luckily still around inside a shared pointer, yet, not part of the current thread (a new stack frame object had appeared with the same stack ID and depth). We now avoid all such issues and properly keep up to date, or we start returning errors when the frame doesn't exist and always responds with invalid answers. Also fixed the UserSettingsController (not going to rewrite this just yet) so that it doesn't crash on shutdown. Using weak_ptr's came in real handy to track when the master controller has already gone away and this allowed me to pull out the previous NotifyOwnerIsShuttingDown() patch as it is no longer needed. llvm-svn: 149231
2012-01-30 07:41:31 +00:00
SBProcess sb_process;
ProcessSP process_sp;
if (IsValid()) {
TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget());
if (target_sp) {
std::lock_guard<std::recursive_mutex> guard(target_sp->GetAPIMutex());
SBFrame is now threadsafe using some extra tricks. One issue is that stack frames might go away (the object itself, not the actual logical frame) when we are single stepping due to the way we currently sometimes end up flushing frames when stepping in/out/over. They later will come back to life represented by another object yet they have the same StackID. Now when you get a lldb::SBFrame object, it will track the frame it is initialized with until the thread goes away or the StackID no longer exists in the stack for the thread it was created on. It uses a weak_ptr to both the frame and thread and also stores the StackID. These three items allow us to determine when the stack frame object has gone away (the weak_ptr will be NULL) and allows us to find the correct frame again. In our test suite we had such cases where we were just getting lucky when something like this happened: 1 - stop at breakpoint 2 - get first frame in thread where we stopped 3 - run an expression that causes the program to JIT and run code 4 - run more expressions on the frame from step 2 which was very very luckily still around inside a shared pointer, yet, not part of the current thread (a new stack frame object had appeared with the same stack ID and depth). We now avoid all such issues and properly keep up to date, or we start returning errors when the frame doesn't exist and always responds with invalid answers. Also fixed the UserSettingsController (not going to rewrite this just yet) so that it doesn't crash on shutdown. Using weak_ptr's came in real handy to track when the master controller has already gone away and this allowed me to pull out the previous NotifyOwnerIsShuttingDown() patch as it is no longer needed. llvm-svn: 149231
2012-01-30 07:41:31 +00:00
process_sp = target_sp->GetProcessSP();
sb_process.SetSP(process_sp);
}
}
return LLDB_RECORD_RESULT(sb_process);
}
SBDebugger SBCommandInterpreter::GetDebugger() {
LLDB_RECORD_METHOD_NO_ARGS(lldb::SBDebugger, SBCommandInterpreter,
GetDebugger);
SBDebugger sb_debugger;
if (IsValid())
sb_debugger.reset(m_opaque_ptr->GetDebugger().shared_from_this());
2010-10-30 04:51:46 +00:00
return LLDB_RECORD_RESULT(sb_debugger);
}
bool SBCommandInterpreter::GetPromptOnQuit() {
LLDB_RECORD_METHOD_NO_ARGS(bool, SBCommandInterpreter, GetPromptOnQuit);
return (IsValid() ? m_opaque_ptr->GetPromptOnQuit() : false);
}
void SBCommandInterpreter::SetPromptOnQuit(bool b) {
LLDB_RECORD_METHOD(void, SBCommandInterpreter, SetPromptOnQuit, (bool), b);
if (IsValid())
m_opaque_ptr->SetPromptOnQuit(b);
}
void SBCommandInterpreter::AllowExitCodeOnQuit(bool allow) {
LLDB_RECORD_METHOD(void, SBCommandInterpreter, AllowExitCodeOnQuit, (bool),
allow);
if (m_opaque_ptr)
m_opaque_ptr->AllowExitCodeOnQuit(allow);
}
bool SBCommandInterpreter::HasCustomQuitExitCode() {
LLDB_RECORD_METHOD_NO_ARGS(bool, SBCommandInterpreter, HasCustomQuitExitCode);
bool exited = false;
if (m_opaque_ptr)
m_opaque_ptr->GetQuitExitCode(exited);
return exited;
}
int SBCommandInterpreter::GetQuitStatus() {
LLDB_RECORD_METHOD_NO_ARGS(int, SBCommandInterpreter, GetQuitStatus);
bool exited = false;
return (m_opaque_ptr ? m_opaque_ptr->GetQuitExitCode(exited) : 0);
}
void SBCommandInterpreter::ResolveCommand(const char *command_line,
SBCommandReturnObject &result) {
LLDB_RECORD_METHOD(void, SBCommandInterpreter, ResolveCommand,
(const char *, lldb::SBCommandReturnObject &),
command_line, result);
result.Clear();
if (command_line && IsValid()) {
m_opaque_ptr->ResolveCommand(command_line, result.ref());
} else {
result->AppendError(
"SBCommandInterpreter or the command line is not valid");
}
}
CommandInterpreter *SBCommandInterpreter::get() { return m_opaque_ptr; }
CommandInterpreter &SBCommandInterpreter::ref() {
assert(m_opaque_ptr);
return *m_opaque_ptr;
}
void SBCommandInterpreter::reset(
lldb_private::CommandInterpreter *interpreter) {
m_opaque_ptr = interpreter;
}
void SBCommandInterpreter::SourceInitFileInHomeDirectory(
SBCommandReturnObject &result) {
LLDB_RECORD_METHOD(void, SBCommandInterpreter, SourceInitFileInHomeDirectory,
(lldb::SBCommandReturnObject &), result);
result.Clear();
if (IsValid()) {
TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget());
std::unique_lock<std::recursive_mutex> lock;
if (target_sp)
lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());
m_opaque_ptr->SourceInitFileHome(result.ref());
} else {
result->AppendError("SBCommandInterpreter is not valid");
}
}
void SBCommandInterpreter::SourceInitFileInHomeDirectory(
SBCommandReturnObject &result, bool is_repl) {
LLDB_RECORD_METHOD(void, SBCommandInterpreter, SourceInitFileInHomeDirectory,
(lldb::SBCommandReturnObject &, bool), result, is_repl);
result.Clear();
if (IsValid()) {
TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget());
std::unique_lock<std::recursive_mutex> lock;
if (target_sp)
lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());
m_opaque_ptr->SourceInitFileHome(result.ref(), is_repl);
} else {
result->AppendError("SBCommandInterpreter is not valid");
}
}
void SBCommandInterpreter::SourceInitFileInCurrentWorkingDirectory(
SBCommandReturnObject &result) {
LLDB_RECORD_METHOD(void, SBCommandInterpreter,
SourceInitFileInCurrentWorkingDirectory,
(lldb::SBCommandReturnObject &), result);
result.Clear();
if (IsValid()) {
TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget());
std::unique_lock<std::recursive_mutex> lock;
if (target_sp)
lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());
m_opaque_ptr->SourceInitFileCwd(result.ref());
} else {
result->AppendError("SBCommandInterpreter is not valid");
}
}
SBBroadcaster SBCommandInterpreter::GetBroadcaster() {
LLDB_RECORD_METHOD_NO_ARGS(lldb::SBBroadcaster, SBCommandInterpreter,
GetBroadcaster);
SBBroadcaster broadcaster(m_opaque_ptr, false);
return LLDB_RECORD_RESULT(broadcaster);
}
const char *SBCommandInterpreter::GetBroadcasterClass() {
LLDB_RECORD_STATIC_METHOD_NO_ARGS(const char *, SBCommandInterpreter,
GetBroadcasterClass);
return CommandInterpreter::GetStaticBroadcasterClass().AsCString();
}
const char *SBCommandInterpreter::GetArgumentTypeAsCString(
const lldb::CommandArgumentType arg_type) {
LLDB_RECORD_STATIC_METHOD(const char *, SBCommandInterpreter,
GetArgumentTypeAsCString,
(const lldb::CommandArgumentType), arg_type);
return CommandObject::GetArgumentTypeAsCString(arg_type);
}
Fix handling of CommandInterpreter's events in lldb-mi Summary: Previously lldb-mi contains a stub for that but it didn't work and all CommanInterpreter's events were ignored. This commit adds a handling of CommandInterpreter's events in lldb-mi. Steps: # Fix CMICmnLLDBDebugger::InitSBListener # Add SBCommandInterpreter::EventIsCommandInterpreterEvent # Exit on lldb::SBCommandInterpreter::eBroadcastBitQuitCommandReceived All tests pass on OS X. In further we can remove "quit" hack in lldb-mi. Test Plan: # Create start_script file: ``` target create ~/p/hello b main r quit ``` # Run lldb-mi --interpreter # Execute start_script file by following command: ``` -interpreter-exec console "command source start_script" ``` Log: ``` $ bin/lldb-mi --interpreter (gdb) -interpreter-exec console "command source start_script" Executing commands in '/Users/IliaK/p/llvm/build_ninja/start_script'. (lldb) target create ~/p/hello Current executable set to '~/p/hello' (x86_64). (lldb) b main Breakpoint 1: where = hello`main + 29 at hello.cpp:12, address = 0x0000000100000e2d (lldb) r Process 1582 launched: '/Users/IliaK/p/hello' (x86_64) (lldb) quit ^done (gdb) =thread-created,id="1",group-id="i1" =thread-selected,id="1" (gdb) =shlibs-added,shlib-info=[num="1",name="hello",dyld-addr="-",reason="dyld",path="/Users/IliaK/p/hello",loaded_addr="-",dsym-objpath="/Users/IliaK/p/hello.dSYM/Contents/Resources/DWARF/hello"] ... =shlibs-added,shlib-info=[num="132",name="libDiagnosticMessagesClient.dylib",dyld-addr="0x7fff91705000",reason="dyld",path="/usr/lib/libDiagnosticMessagesClient.dylib",loaded_addr="0x7fff91705000"] (gdb) *stopped,reason="breakpoint-hit",disp="del",bkptno="1",frame={addr="0x100000e2d",func="main",args=[{name="argc",value="1"},{name="argv",value="0x00007fff5fbffc88"}],file="hello.cpp",fullname="/Users/IliaK/p/hello.cpp",line="12"},thread-id="1",stopped-threads="all" (gdb)<press Enter> MI: Program exited OK ``` Reviewers: abidh, clayborg Reviewed By: abidh Subscribers: jingham, lldb-commits, clayborg, abidh Differential Revision: http://reviews.llvm.org/D8382 llvm-svn: 232891
2015-03-21 10:53:37 +00:00
const char *SBCommandInterpreter::GetArgumentDescriptionAsCString(
const lldb::CommandArgumentType arg_type) {
LLDB_RECORD_STATIC_METHOD(const char *, SBCommandInterpreter,
GetArgumentDescriptionAsCString,
(const lldb::CommandArgumentType), arg_type);
return CommandObject::GetArgumentDescriptionAsCString(arg_type);
Fix handling of CommandInterpreter's events in lldb-mi Summary: Previously lldb-mi contains a stub for that but it didn't work and all CommanInterpreter's events were ignored. This commit adds a handling of CommandInterpreter's events in lldb-mi. Steps: # Fix CMICmnLLDBDebugger::InitSBListener # Add SBCommandInterpreter::EventIsCommandInterpreterEvent # Exit on lldb::SBCommandInterpreter::eBroadcastBitQuitCommandReceived All tests pass on OS X. In further we can remove "quit" hack in lldb-mi. Test Plan: # Create start_script file: ``` target create ~/p/hello b main r quit ``` # Run lldb-mi --interpreter # Execute start_script file by following command: ``` -interpreter-exec console "command source start_script" ``` Log: ``` $ bin/lldb-mi --interpreter (gdb) -interpreter-exec console "command source start_script" Executing commands in '/Users/IliaK/p/llvm/build_ninja/start_script'. (lldb) target create ~/p/hello Current executable set to '~/p/hello' (x86_64). (lldb) b main Breakpoint 1: where = hello`main + 29 at hello.cpp:12, address = 0x0000000100000e2d (lldb) r Process 1582 launched: '/Users/IliaK/p/hello' (x86_64) (lldb) quit ^done (gdb) =thread-created,id="1",group-id="i1" =thread-selected,id="1" (gdb) =shlibs-added,shlib-info=[num="1",name="hello",dyld-addr="-",reason="dyld",path="/Users/IliaK/p/hello",loaded_addr="-",dsym-objpath="/Users/IliaK/p/hello.dSYM/Contents/Resources/DWARF/hello"] ... =shlibs-added,shlib-info=[num="132",name="libDiagnosticMessagesClient.dylib",dyld-addr="0x7fff91705000",reason="dyld",path="/usr/lib/libDiagnosticMessagesClient.dylib",loaded_addr="0x7fff91705000"] (gdb) *stopped,reason="breakpoint-hit",disp="del",bkptno="1",frame={addr="0x100000e2d",func="main",args=[{name="argc",value="1"},{name="argv",value="0x00007fff5fbffc88"}],file="hello.cpp",fullname="/Users/IliaK/p/hello.cpp",line="12"},thread-id="1",stopped-threads="all" (gdb)<press Enter> MI: Program exited OK ``` Reviewers: abidh, clayborg Reviewed By: abidh Subscribers: jingham, lldb-commits, clayborg, abidh Differential Revision: http://reviews.llvm.org/D8382 llvm-svn: 232891
2015-03-21 10:53:37 +00:00
}
bool SBCommandInterpreter::EventIsCommandInterpreterEvent(
const lldb::SBEvent &event) {
LLDB_RECORD_STATIC_METHOD(bool, SBCommandInterpreter,
EventIsCommandInterpreterEvent,
(const lldb::SBEvent &), event);
return event.GetBroadcasterClass() ==
SBCommandInterpreter::GetBroadcasterClass();
}
bool SBCommandInterpreter::SetCommandOverrideCallback(
const char *command_name, lldb::CommandOverrideCallback callback,
void *baton) {
LLDB_RECORD_DUMMY(bool, SBCommandInterpreter, SetCommandOverrideCallback,
(const char *, lldb::CommandOverrideCallback, void *),
command_name, callback, baton);
if (command_name && command_name[0] && IsValid()) {
llvm::StringRef command_name_str = command_name;
CommandObject *cmd_obj =
m_opaque_ptr->GetCommandObjectForCommand(command_name_str);
if (cmd_obj) {
assert(command_name_str.empty());
cmd_obj->SetOverrideCallback(callback, baton);
return true;
}
}
return false;
}
lldb::SBCommand SBCommandInterpreter::AddMultiwordCommand(const char *name,
const char *help) {
LLDB_RECORD_METHOD(lldb::SBCommand, SBCommandInterpreter, AddMultiwordCommand,
(const char *, const char *), name, help);
lldb::CommandObjectSP new_command_sp(
new CommandObjectMultiword(*m_opaque_ptr, name, help));
new_command_sp->GetAsMultiwordCommand()->SetRemovable(true);
Status add_error = m_opaque_ptr->AddUserCommand(name, new_command_sp, true);
if (add_error.Success())
return LLDB_RECORD_RESULT(lldb::SBCommand(new_command_sp));
return LLDB_RECORD_RESULT(lldb::SBCommand());
}
lldb::SBCommand SBCommandInterpreter::AddCommand(
const char *name, lldb::SBCommandPluginInterface *impl, const char *help) {
LLDB_RECORD_METHOD(
lldb::SBCommand, SBCommandInterpreter, AddCommand,
(const char *, lldb::SBCommandPluginInterface *, const char *), name,
impl, help);
return LLDB_RECORD_RESULT(AddCommand(name, impl, help, /*syntax=*/nullptr,
/*auto_repeat_command=*/""))
}
lldb::SBCommand
SBCommandInterpreter::AddCommand(const char *name,
lldb::SBCommandPluginInterface *impl,
const char *help, const char *syntax) {
LLDB_RECORD_METHOD(lldb::SBCommand, SBCommandInterpreter, AddCommand,
(const char *, lldb::SBCommandPluginInterface *,
const char *, const char *),
name, impl, help, syntax);
return LLDB_RECORD_RESULT(
AddCommand(name, impl, help, syntax, /*auto_repeat_command=*/""))
}
lldb::SBCommand SBCommandInterpreter::AddCommand(
const char *name, lldb::SBCommandPluginInterface *impl, const char *help,
const char *syntax, const char *auto_repeat_command) {
LLDB_RECORD_METHOD(lldb::SBCommand, SBCommandInterpreter, AddCommand,
(const char *, lldb::SBCommandPluginInterface *,
const char *, const char *, const char *),
name, impl, help, syntax, auto_repeat_command);
lldb::CommandObjectSP new_command_sp;
new_command_sp = std::make_shared<CommandPluginInterfaceImplementation>(
*m_opaque_ptr, name, impl, help, syntax, /*flags=*/0,
auto_repeat_command);
Status add_error = m_opaque_ptr->AddUserCommand(name, new_command_sp, true);
if (add_error.Success())
return LLDB_RECORD_RESULT(lldb::SBCommand(new_command_sp));
return LLDB_RECORD_RESULT(lldb::SBCommand());
}
SBCommand::SBCommand() { LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBCommand); }
SBCommand::SBCommand(lldb::CommandObjectSP cmd_sp) : m_opaque_sp(cmd_sp) {}
bool SBCommand::IsValid() {
LLDB_RECORD_METHOD_NO_ARGS(bool, SBCommand, IsValid);
return this->operator bool();
}
SBCommand::operator bool() const {
LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBCommand, operator bool);
return m_opaque_sp.get() != nullptr;
}
const char *SBCommand::GetName() {
LLDB_RECORD_METHOD_NO_ARGS(const char *, SBCommand, GetName);
return (IsValid() ? ConstString(m_opaque_sp->GetCommandName()).AsCString() : nullptr);
}
const char *SBCommand::GetHelp() {
LLDB_RECORD_METHOD_NO_ARGS(const char *, SBCommand, GetHelp);
return (IsValid() ? ConstString(m_opaque_sp->GetHelp()).AsCString()
: nullptr);
}
const char *SBCommand::GetHelpLong() {
LLDB_RECORD_METHOD_NO_ARGS(const char *, SBCommand, GetHelpLong);
return (IsValid() ? ConstString(m_opaque_sp->GetHelpLong()).AsCString()
: nullptr);
}
void SBCommand::SetHelp(const char *help) {
LLDB_RECORD_METHOD(void, SBCommand, SetHelp, (const char *), help);
if (IsValid())
m_opaque_sp->SetHelp(help);
}
void SBCommand::SetHelpLong(const char *help) {
LLDB_RECORD_METHOD(void, SBCommand, SetHelpLong, (const char *), help);
if (IsValid())
m_opaque_sp->SetHelpLong(help);
}
lldb::SBCommand SBCommand::AddMultiwordCommand(const char *name,
const char *help) {
LLDB_RECORD_METHOD(lldb::SBCommand, SBCommand, AddMultiwordCommand,
(const char *, const char *), name, help);
if (!IsValid())
return LLDB_RECORD_RESULT(lldb::SBCommand());
if (!m_opaque_sp->IsMultiwordObject())
return LLDB_RECORD_RESULT(lldb::SBCommand());
CommandObjectMultiword *new_command = new CommandObjectMultiword(
m_opaque_sp->GetCommandInterpreter(), name, help);
new_command->SetRemovable(true);
lldb::CommandObjectSP new_command_sp(new_command);
if (new_command_sp && m_opaque_sp->LoadSubCommand(name, new_command_sp))
return LLDB_RECORD_RESULT(lldb::SBCommand(new_command_sp));
return LLDB_RECORD_RESULT(lldb::SBCommand());
}
lldb::SBCommand SBCommand::AddCommand(const char *name,
lldb::SBCommandPluginInterface *impl,
const char *help) {
LLDB_RECORD_METHOD(
lldb::SBCommand, SBCommand, AddCommand,
(const char *, lldb::SBCommandPluginInterface *, const char *), name,
impl, help);
return LLDB_RECORD_RESULT(AddCommand(name, impl, help, /*syntax=*/nullptr,
/*auto_repeat_command=*/""))
}
lldb::SBCommand SBCommand::AddCommand(const char *name,
lldb::SBCommandPluginInterface *impl,
const char *help, const char *syntax) {
LLDB_RECORD_METHOD(lldb::SBCommand, SBCommand, AddCommand,
(const char *, lldb::SBCommandPluginInterface *,
const char *, const char *),
name, impl, help, syntax);
return LLDB_RECORD_RESULT(
AddCommand(name, impl, help, syntax, /*auto_repeat_command=*/""))
}
lldb::SBCommand SBCommand::AddCommand(const char *name,
lldb::SBCommandPluginInterface *impl,
const char *help, const char *syntax,
const char *auto_repeat_command) {
LLDB_RECORD_METHOD(lldb::SBCommand, SBCommand, AddCommand,
(const char *, lldb::SBCommandPluginInterface *,
const char *, const char *, const char *),
name, impl, help, syntax, auto_repeat_command);
if (!IsValid())
return LLDB_RECORD_RESULT(lldb::SBCommand());
if (!m_opaque_sp->IsMultiwordObject())
return LLDB_RECORD_RESULT(lldb::SBCommand());
lldb::CommandObjectSP new_command_sp;
new_command_sp = std::make_shared<CommandPluginInterfaceImplementation>(
m_opaque_sp->GetCommandInterpreter(), name, impl, help, syntax,
/*flags=*/0, auto_repeat_command);
if (new_command_sp && m_opaque_sp->LoadSubCommand(name, new_command_sp))
return LLDB_RECORD_RESULT(lldb::SBCommand(new_command_sp));
return LLDB_RECORD_RESULT(lldb::SBCommand());
}
uint32_t SBCommand::GetFlags() {
LLDB_RECORD_METHOD_NO_ARGS(uint32_t, SBCommand, GetFlags);
return (IsValid() ? m_opaque_sp->GetFlags().Get() : 0);
}
void SBCommand::SetFlags(uint32_t flags) {
LLDB_RECORD_METHOD(void, SBCommand, SetFlags, (uint32_t), flags);
if (IsValid())
m_opaque_sp->GetFlags().Set(flags);
}
namespace lldb_private {
namespace repro {
template <> void RegisterMethods<SBCommandInterpreter>(Registry &R) {
LLDB_REGISTER_CONSTRUCTOR(SBCommandInterpreter,
(lldb_private::CommandInterpreter *));
LLDB_REGISTER_CONSTRUCTOR(SBCommandInterpreter,
(const lldb::SBCommandInterpreter &));
LLDB_REGISTER_METHOD(
const lldb::SBCommandInterpreter &,
SBCommandInterpreter, operator=,(const lldb::SBCommandInterpreter &));
LLDB_REGISTER_METHOD_CONST(bool, SBCommandInterpreter, IsValid, ());
LLDB_REGISTER_METHOD_CONST(bool, SBCommandInterpreter, operator bool, ());
LLDB_REGISTER_METHOD(bool, SBCommandInterpreter, CommandExists,
(const char *));
LLDB_REGISTER_METHOD(bool, SBCommandInterpreter, AliasExists,
(const char *));
LLDB_REGISTER_METHOD(bool, SBCommandInterpreter, IsActive, ());
LLDB_REGISTER_METHOD_CONST(bool, SBCommandInterpreter, WasInterrupted, ());
LLDB_REGISTER_METHOD(const char *, SBCommandInterpreter,
GetIOHandlerControlSequence, (char));
LLDB_REGISTER_METHOD(lldb::ReturnStatus, SBCommandInterpreter,
HandleCommand,
(const char *, lldb::SBCommandReturnObject &, bool));
LLDB_REGISTER_METHOD(lldb::ReturnStatus, SBCommandInterpreter,
HandleCommand,
(const char *, lldb::SBExecutionContext &,
lldb::SBCommandReturnObject &, bool));
LLDB_REGISTER_METHOD(void, SBCommandInterpreter, HandleCommandsFromFile,
(lldb::SBFileSpec &, lldb::SBExecutionContext &,
lldb::SBCommandInterpreterRunOptions &,
lldb::SBCommandReturnObject));
LLDB_REGISTER_METHOD(int, SBCommandInterpreter, HandleCompletion,
(const char *, const char *, const char *, int, int,
lldb::SBStringList &));
LLDB_REGISTER_METHOD(int, SBCommandInterpreter,
HandleCompletionWithDescriptions,
(const char *, const char *, const char *, int, int,
lldb::SBStringList &, lldb::SBStringList &));
LLDB_REGISTER_METHOD(int, SBCommandInterpreter,
HandleCompletionWithDescriptions,
(const char *, uint32_t, int, int,
lldb::SBStringList &, lldb::SBStringList &));
LLDB_REGISTER_METHOD(
int, SBCommandInterpreter, HandleCompletion,
(const char *, uint32_t, int, int, lldb::SBStringList &));
LLDB_REGISTER_METHOD(bool, SBCommandInterpreter, HasCommands, ());
LLDB_REGISTER_METHOD(bool, SBCommandInterpreter, HasAliases, ());
LLDB_REGISTER_METHOD(bool, SBCommandInterpreter, HasAliasOptions, ());
LLDB_REGISTER_METHOD(lldb::SBProcess, SBCommandInterpreter, GetProcess, ());
LLDB_REGISTER_METHOD(lldb::SBDebugger, SBCommandInterpreter, GetDebugger,
());
LLDB_REGISTER_METHOD(bool, SBCommandInterpreter, GetPromptOnQuit, ());
LLDB_REGISTER_METHOD(void, SBCommandInterpreter, SetPromptOnQuit, (bool));
LLDB_REGISTER_METHOD(void, SBCommandInterpreter, AllowExitCodeOnQuit,
(bool));
LLDB_REGISTER_METHOD(bool, SBCommandInterpreter, HasCustomQuitExitCode, ());
LLDB_REGISTER_METHOD(int, SBCommandInterpreter, GetQuitStatus, ());
LLDB_REGISTER_METHOD(void, SBCommandInterpreter, ResolveCommand,
(const char *, lldb::SBCommandReturnObject &));
LLDB_REGISTER_METHOD(void, SBCommandInterpreter,
SourceInitFileInHomeDirectory,
(lldb::SBCommandReturnObject &));
LLDB_REGISTER_METHOD(void, SBCommandInterpreter,
SourceInitFileInHomeDirectory,
(lldb::SBCommandReturnObject &, bool));
LLDB_REGISTER_METHOD(void, SBCommandInterpreter,
SourceInitFileInCurrentWorkingDirectory,
(lldb::SBCommandReturnObject &));
LLDB_REGISTER_METHOD(lldb::SBBroadcaster, SBCommandInterpreter,
GetBroadcaster, ());
LLDB_REGISTER_STATIC_METHOD(const char *, SBCommandInterpreter,
GetBroadcasterClass, ());
LLDB_REGISTER_STATIC_METHOD(const char *, SBCommandInterpreter,
GetArgumentTypeAsCString,
(const lldb::CommandArgumentType));
LLDB_REGISTER_STATIC_METHOD(const char *, SBCommandInterpreter,
GetArgumentDescriptionAsCString,
(const lldb::CommandArgumentType));
LLDB_REGISTER_STATIC_METHOD(bool, SBCommandInterpreter,
EventIsCommandInterpreterEvent,
(const lldb::SBEvent &));
LLDB_REGISTER_METHOD(lldb::SBCommand, SBCommandInterpreter,
AddMultiwordCommand, (const char *, const char *));
LLDB_REGISTER_METHOD(
lldb::SBCommand, SBCommandInterpreter, AddCommand,
(const char *, lldb::SBCommandPluginInterface *, const char *));
LLDB_REGISTER_METHOD(lldb::SBCommand, SBCommandInterpreter, AddCommand,
(const char *, lldb::SBCommandPluginInterface *,
const char *, const char *));
LLDB_REGISTER_METHOD(lldb::SBCommand, SBCommandInterpreter, AddCommand,
(const char *, lldb::SBCommandPluginInterface *,
const char *, const char *, const char *));
LLDB_REGISTER_CONSTRUCTOR(SBCommand, ());
LLDB_REGISTER_METHOD(bool, SBCommand, IsValid, ());
LLDB_REGISTER_METHOD_CONST(bool, SBCommand, operator bool, ());
LLDB_REGISTER_METHOD(const char *, SBCommand, GetName, ());
LLDB_REGISTER_METHOD(const char *, SBCommand, GetHelp, ());
LLDB_REGISTER_METHOD(const char *, SBCommand, GetHelpLong, ());
LLDB_REGISTER_METHOD(void, SBCommand, SetHelp, (const char *));
LLDB_REGISTER_METHOD(void, SBCommand, SetHelpLong, (const char *));
LLDB_REGISTER_METHOD(lldb::SBCommand, SBCommand, AddMultiwordCommand,
(const char *, const char *));
LLDB_REGISTER_METHOD(
lldb::SBCommand, SBCommand, AddCommand,
(const char *, lldb::SBCommandPluginInterface *, const char *));
LLDB_REGISTER_METHOD(lldb::SBCommand, SBCommand, AddCommand,
(const char *, lldb::SBCommandPluginInterface *,
const char *, const char *));
LLDB_REGISTER_METHOD(lldb::SBCommand, SBCommand, AddCommand,
(const char *, lldb::SBCommandPluginInterface *,
const char *, const char *, const char *));
LLDB_REGISTER_METHOD(uint32_t, SBCommand, GetFlags, ());
LLDB_REGISTER_METHOD(void, SBCommand, SetFlags, (uint32_t));
}
}
}