diff options
Diffstat (limited to 'source/Commands/CommandObjectExpression.cpp')
-rw-r--r-- | source/Commands/CommandObjectExpression.cpp | 104 |
1 files changed, 84 insertions, 20 deletions
diff --git a/source/Commands/CommandObjectExpression.cpp b/source/Commands/CommandObjectExpression.cpp index 08959ff8473d..e87d68a53da4 100644 --- a/source/Commands/CommandObjectExpression.cpp +++ b/source/Commands/CommandObjectExpression.cpp @@ -7,13 +7,9 @@ // //===----------------------------------------------------------------------===// -// C Includes -// C++ Includes -// Other libraries and framework includes #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" -// Project includes #include "CommandObjectExpression.h" #include "Plugins/ExpressionParser/Clang/ClangExpressionVariable.h" #include "lldb/Core/Debugger.h" @@ -43,29 +39,32 @@ CommandObjectExpression::CommandOptions::CommandOptions() : OptionGroup() {} CommandObjectExpression::CommandOptions::~CommandOptions() = default; -static OptionEnumValueElement g_description_verbosity_type[] = { +static constexpr OptionEnumValueElement g_description_verbosity_type[] = { {eLanguageRuntimeDescriptionDisplayVerbosityCompact, "compact", "Only show the description string"}, {eLanguageRuntimeDescriptionDisplayVerbosityFull, "full", - "Show the full output, including persistent variable's name and type"}, - {0, nullptr, nullptr}}; + "Show the full output, including persistent variable's name and type"} }; -static OptionDefinition g_expression_options[] = { +static constexpr OptionEnumValues DescriptionVerbosityTypes() { + return OptionEnumValues(g_description_verbosity_type); +} + +static constexpr OptionDefinition g_expression_options[] = { // clang-format off - {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "all-threads", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Should we run all threads if the execution doesn't complete on one thread."}, - {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "ignore-breakpoints", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Ignore breakpoint hits while running expressions"}, - {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "timeout", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Timeout value (in microseconds) for running the expression."}, - {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "unwind-on-error", 'u', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Clean up program state if the expression causes a crash, or raises a signal. " + {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "all-threads", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Should we run all threads if the execution doesn't complete on one thread."}, + {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "ignore-breakpoints", 'i', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Ignore breakpoint hits while running expressions"}, + {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "timeout", 't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "Timeout value (in microseconds) for running the expression."}, + {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "unwind-on-error", 'u', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Clean up program state if the expression causes a crash, or raises a signal. " "Note, unlike gdb hitting a breakpoint is controlled by another option (-i)."}, - {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "debug", 'g', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "When specified, debug the JIT code by setting a breakpoint on the first instruction " + {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "debug", 'g', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "When specified, debug the JIT code by setting a breakpoint on the first instruction " "and forcing breakpoints to not be ignored (-i0) and no unwinding to happen on error (-u0)."}, - {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Specifies the Language to use when parsing the expression. If not set the target.language " + {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Specifies the Language to use when parsing the expression. If not set the target.language " "setting is used." }, - {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "apply-fixits", 'X', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "If true, simple fix-it hints will be automatically applied to the expression." }, - {LLDB_OPT_SET_1, false, "description-verbosity", 'v', OptionParser::eOptionalArgument, nullptr, g_description_verbosity_type, 0, eArgTypeDescriptionVerbosity, "How verbose should the output of this expression be, if the object description is asked for."}, - {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "top-level", 'p', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Interpret the expression as a complete translation unit, without injecting it into the local " + {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "apply-fixits", 'X', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "If true, simple fix-it hints will be automatically applied to the expression." }, + {LLDB_OPT_SET_1, false, "description-verbosity", 'v', OptionParser::eOptionalArgument, nullptr, DescriptionVerbosityTypes(), 0, eArgTypeDescriptionVerbosity, "How verbose should the output of this expression be, if the object description is asked for."}, + {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "top-level", 'p', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Interpret the expression as a complete translation unit, without injecting it into the local " "context. Allows declaration of persistent, top-level entities without a $ prefix."}, - {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "allow-jit", 'j', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Controls whether the expression can fall back to being JITted if it's not supported by " + {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "allow-jit", 'j', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Controls whether the expression can fall back to being JITted if it's not supported by " "the interpreter (defaults to true)."} // clang-format on }; @@ -307,6 +306,72 @@ CommandObjectExpression::~CommandObjectExpression() = default; Options *CommandObjectExpression::GetOptions() { return &m_option_group; } +int CommandObjectExpression::HandleCompletion(CompletionRequest &request) { + EvaluateExpressionOptions options; + options.SetCoerceToId(m_varobj_options.use_objc); + options.SetLanguage(m_command_options.language); + options.SetExecutionPolicy(lldb_private::eExecutionPolicyNever); + options.SetAutoApplyFixIts(false); + options.SetGenerateDebugInfo(false); + + // We need a valid execution context with a frame pointer for this + // completion, so if we don't have one we should try to make a valid + // execution context. + if (m_interpreter.GetExecutionContext().GetFramePtr() == nullptr) + m_interpreter.UpdateExecutionContext(nullptr); + + // This didn't work, so let's get out before we start doing things that + // expect a valid frame pointer. + if (m_interpreter.GetExecutionContext().GetFramePtr() == nullptr) + return 0; + + ExecutionContext exe_ctx(m_interpreter.GetExecutionContext()); + + Target *target = exe_ctx.GetTargetPtr(); + + if (!target) + target = GetDummyTarget(); + + if (!target) + return 0; + + unsigned cursor_pos = request.GetRawCursorPos(); + llvm::StringRef code = request.GetRawLine(); + + const std::size_t original_code_size = code.size(); + + // Remove the first token which is 'expr' or some alias/abbreviation of that. + code = llvm::getToken(code).second.ltrim(); + OptionsWithRaw args(code); + code = args.GetRawPart(); + + // The position where the expression starts in the command line. + assert(original_code_size >= code.size()); + std::size_t raw_start = original_code_size - code.size(); + + // Check if the cursor is actually in the expression string, and if not, we + // exit. + // FIXME: We should complete the options here. + if (cursor_pos < raw_start) + return 0; + + // Make the cursor_pos again relative to the start of the code string. + assert(cursor_pos >= raw_start); + cursor_pos -= raw_start; + + auto language = exe_ctx.GetFrameRef().GetLanguage(); + + Status error; + lldb::UserExpressionSP expr(target->GetUserExpressionForLanguage( + code, llvm::StringRef(), language, UserExpression::eResultTypeAny, + options, error)); + if (error.Fail()) + return 0; + + expr->Complete(exe_ctx, request, cursor_pos); + return request.GetNumberOfMatches(); +} + static lldb_private::Status CanBeUsedForElementCountPrinting(ValueObject &valobj) { CompilerType type(valobj.GetCompilerType()); @@ -355,8 +420,7 @@ bool CommandObjectExpression::EvaluateExpression(llvm::StringRef expr, if (m_command_options.auto_apply_fixits == eLazyBoolCalculate) auto_apply_fixits = target->GetEnableAutoApplyFixIts(); else - auto_apply_fixits = - m_command_options.auto_apply_fixits == eLazyBoolYes ? true : false; + auto_apply_fixits = m_command_options.auto_apply_fixits == eLazyBoolYes; options.SetAutoApplyFixIts(auto_apply_fixits); |