@@ -594,63 +594,58 @@ lldb::SBFrame DAP::GetLLDBFrame(const llvm::json::Object &arguments) {
594594 return GetLLDBFrame (frame_id);
595595}
596596
597- ReplMode DAP::DetectReplMode (lldb::SBFrame frame, std::string &expression,
597+ ReplMode DAP::DetectReplMode (lldb::SBFrame & frame, std::string &expression,
598598 bool partial_expression) {
599599 // Check for the escape hatch prefix.
600- if (!expression.empty () &&
601- llvm::StringRef (expression)
602- .starts_with (configuration.commandEscapePrefix )) {
603- expression = expression.substr (configuration.commandEscapePrefix .size ());
600+ if (llvm::StringRef expr_ref = expression;
601+ expr_ref.consume_front (configuration.commandEscapePrefix )) {
602+ expression = expr_ref;
604603 return ReplMode::Command;
605604 }
606605
607- switch (repl_mode) {
608- case ReplMode::Variable:
609- return ReplMode::Variable;
610- case ReplMode::Command:
611- return ReplMode::Command;
612- case ReplMode::Auto:
613- // To determine if the expression is a command or not, check if the first
614- // term is a variable or command. If it's a variable in scope we will prefer
615- // that behavior and give a warning to the user if they meant to invoke the
616- // operation as a command.
617- //
618- // Example use case:
619- // int p and expression "p + 1" > variable
620- // int i and expression "i" > variable
621- // int var and expression "va" > command
622- std::pair<llvm::StringRef, llvm::StringRef> token =
623- llvm::getToken (expression);
624-
625- // If the first token is not fully finished yet, we can't
626- // determine whether this will be a variable or a lldb command.
627- if (partial_expression && token.second .empty ())
628- return ReplMode::Auto;
629-
630- std::string term = token.first .str ();
631- lldb::SBCommandInterpreter interpreter = debugger.GetCommandInterpreter ();
632- bool term_is_command = interpreter.CommandExists (term.c_str ()) ||
633- interpreter.UserCommandExists (term.c_str ()) ||
634- interpreter.AliasExists (term.c_str ());
635- bool term_is_variable = frame.FindVariable (term.c_str ()).IsValid ();
636-
637- // If we have both a variable and command, warn the user about the conflict.
638- if (term_is_command && term_is_variable) {
639- llvm::errs ()
640- << " Warning: Expression '" << term
641- << " ' is both an LLDB command and variable. It will be evaluated as "
642- " a variable. To evaluate the expression as an LLDB command, use '"
643- << configuration.commandEscapePrefix << " ' as a prefix.\n " ;
644- }
645-
646- // Variables take preference to commands in auto, since commands can always
647- // be called using the command_escape_prefix
648- return term_is_variable ? ReplMode::Variable
649- : term_is_command ? ReplMode::Command
650- : ReplMode::Variable;
606+ if (repl_mode != ReplMode::Auto)
607+ return repl_mode;
608+ // To determine if the expression is a command or not, check if the first
609+ // term is a variable or command. If it's a variable in scope we will prefer
610+ // that behavior and give a warning to the user if they meant to invoke the
611+ // operation as a command.
612+ //
613+ // Example use case:
614+ // int p and expression "p + 1" > variable
615+ // int i and expression "i" > variable
616+ // int var and expression "va" > command
617+ const auto [first_tok, remaining] = llvm::getToken (expression);
618+
619+ // If the first token is not fully finished yet, we can't
620+ // determine whether this will be a variable or a lldb command.
621+ if (partial_expression && remaining.empty ())
622+ return ReplMode::Auto;
623+
624+ std::string first = first_tok.str ();
625+ const char *first_cstr = first.c_str ();
626+ lldb::SBCommandInterpreter interpreter = debugger.GetCommandInterpreter ();
627+ const bool is_command = interpreter.CommandExists (first_cstr) ||
628+ interpreter.UserCommandExists (first_cstr) ||
629+ interpreter.AliasExists (first_cstr);
630+ const bool is_variable = frame.FindVariable (first_cstr).IsValid ();
631+
632+ // If we have both a variable and command, warn the user about the conflict.
633+ if (!partial_expression && is_command && is_variable) {
634+ const std::string warning_msg =
635+ llvm::formatv (" warning: Expression '{}' is both an LLDB command and "
636+ " variable. It will be evaluated as "
637+ " a variable. To evaluate the expression as an LLDB "
638+ " command, use '{}' as a prefix.\n " ,
639+ first, configuration.commandEscapePrefix );
640+ SendOutput (OutputType::Console, warning_msg);
651641 }
652642
653- llvm_unreachable (" enum cases exhausted." );
643+ // Variables take preference to commands in auto, since commands can always
644+ // be called using the command_escape_prefix
645+ if (is_variable)
646+ return ReplMode::Variable;
647+
648+ return is_command ? ReplMode::Command : ReplMode::Variable;
654649}
655650
656651std::optional<protocol::Source> DAP::ResolveSource (const lldb::SBFrame &frame) {
0 commit comments