diff options
Diffstat (limited to 'lldb/source/Commands/CommandObjectDWIMPrint.cpp')
| -rw-r--r-- | lldb/source/Commands/CommandObjectDWIMPrint.cpp | 88 |
1 files changed, 77 insertions, 11 deletions
diff --git a/lldb/source/Commands/CommandObjectDWIMPrint.cpp b/lldb/source/Commands/CommandObjectDWIMPrint.cpp index b2b7f201a5ad..695f3d7931cd 100644 --- a/lldb/source/Commands/CommandObjectDWIMPrint.cpp +++ b/lldb/source/Commands/CommandObjectDWIMPrint.cpp @@ -25,6 +25,8 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/FormatVariadic.h" +#include <regex> + using namespace llvm; using namespace lldb; using namespace lldb_private; @@ -56,7 +58,7 @@ void CommandObjectDWIMPrint::HandleArgumentCompletion( GetCommandInterpreter(), lldb::eVariablePathCompletion, request, nullptr); } -bool CommandObjectDWIMPrint::DoExecute(StringRef command, +void CommandObjectDWIMPrint::DoExecute(StringRef command, CommandReturnObject &result) { m_option_group.NotifyOptionParsingStarting(&m_exe_ctx); OptionsWithRaw args{command}; @@ -65,13 +67,13 @@ bool CommandObjectDWIMPrint::DoExecute(StringRef command, if (expr.empty()) { result.AppendErrorWithFormatv("'{0}' takes a variable or expression", m_cmd_name); - return false; + return; } if (args.HasArgs()) { if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group, m_exe_ctx)) - return false; + return; } // If the user has not specified, default to disabling persistent results. @@ -95,8 +97,46 @@ bool CommandObjectDWIMPrint::DoExecute(StringRef command, m_expr_options.m_verbosity, m_format_options.GetFormat()); dump_options.SetHideRootName(suppress_result); + bool is_po = m_varobj_options.use_objc; + StackFrame *frame = m_exe_ctx.GetFramePtr(); + // Either Swift was explicitly specified, or the frame is Swift. + lldb::LanguageType language = m_expr_options.language; + if (language == lldb::eLanguageTypeUnknown && frame) + language = frame->GuessLanguage(); + + // Add a hint if object description was requested, but no description + // function was implemented. + auto maybe_add_hint = [&](llvm::StringRef output) { + // Identify the default output of object description for Swift and + // Objective-C + // "<Name: 0x...>. The regex is: + // - Start with "<". + // - Followed by 1 or more non-whitespace characters. + // - Followed by ": 0x". + // - Followed by 5 or more hex digits. + // - Followed by ">". + // - End with zero or more whitespace characters. + const std::regex swift_class_regex("^<\\S+: 0x[[:xdigit:]]{5,}>\\s*$"); + + if (GetDebugger().GetShowDontUsePoHint() && target_ptr && + (language == lldb::eLanguageTypeSwift || + language == lldb::eLanguageTypeObjC) && + std::regex_match(output.data(), swift_class_regex)) { + + static bool note_shown = false; + if (note_shown) + return; + + result.GetOutputStream() + << "note: object description requested, but type doesn't implement " + "a custom object description. Consider using \"p\" instead of " + "\"po\" (this note will only be shown once per debug session).\n"; + note_shown = true; + } + }; + // First, try `expr` as the name of a frame variable. if (frame) { auto valobj_sp = frame->FindVariable(ConstString(expr)); @@ -114,9 +154,17 @@ bool CommandObjectDWIMPrint::DoExecute(StringRef command, flags, expr); } - valobj_sp->Dump(result.GetOutputStream(), dump_options); + if (is_po) { + StreamString temp_result_stream; + valobj_sp->Dump(temp_result_stream, dump_options); + llvm::StringRef output = temp_result_stream.GetString(); + maybe_add_hint(output); + result.GetOutputStream() << output; + } else { + valobj_sp->Dump(result.GetOutputStream(), dump_options); + } result.SetStatus(eReturnStatusSuccessFinishResult); - return true; + return; } } @@ -124,8 +172,19 @@ bool CommandObjectDWIMPrint::DoExecute(StringRef command, { auto *exe_scope = m_exe_ctx.GetBestExecutionContextScope(); ValueObjectSP valobj_sp; - ExpressionResults expr_result = - target.EvaluateExpression(expr, exe_scope, valobj_sp, eval_options); + std::string fixed_expression; + + ExpressionResults expr_result = target.EvaluateExpression( + expr, exe_scope, valobj_sp, eval_options, &fixed_expression); + + // Only mention Fix-Its if the expression evaluator applied them. + // Compiler errors refer to the final expression after applying Fix-It(s). + if (!fixed_expression.empty() && target.GetEnableNotifyAboutFixIts()) { + Stream &error_stream = result.GetErrorStream(); + error_stream << " Evaluated this expression after applying Fix-It(s):\n"; + error_stream << " " << fixed_expression << "\n"; + } + if (expr_result == eExpressionCompleted) { if (verbosity != eDWIMPrintVerbosityNone) { StringRef flags; @@ -135,8 +194,17 @@ bool CommandObjectDWIMPrint::DoExecute(StringRef command, expr); } - if (valobj_sp->GetError().GetError() != UserExpression::kNoResult) - valobj_sp->Dump(result.GetOutputStream(), dump_options); + if (valobj_sp->GetError().GetError() != UserExpression::kNoResult) { + if (is_po) { + StreamString temp_result_stream; + valobj_sp->Dump(temp_result_stream, dump_options); + llvm::StringRef output = temp_result_stream.GetString(); + maybe_add_hint(output); + result.GetOutputStream() << output; + } else { + valobj_sp->Dump(result.GetOutputStream(), dump_options); + } + } if (suppress_result) if (auto result_var_sp = @@ -148,14 +216,12 @@ bool CommandObjectDWIMPrint::DoExecute(StringRef command, } result.SetStatus(eReturnStatusSuccessFinishResult); - return true; } else { if (valobj_sp) result.SetError(valobj_sp->GetError()); else result.AppendErrorWithFormatv( "unknown error evaluating expression `{0}`", expr); - return false; } } } |
