Skip to content

Commit 8c8607d

Browse files
committed
[lldb/Interpreter] Fix ambiguous partial command resolution
This patch is a follow-up to llvm#97263 that fix ambigous abbreviated command resolution. When multiple commands are resolved, instead of failing to pick a command to run, this patch changes to resolution logic to check if there is either a single user command match or a single alias match and if so, it will run that command instead of the others. This has as a side-effect that we don't need to make aliases for every substring of aliases to support abbrivated alias resolution. Signed-off-by: Med Ismail Bennani <[email protected]>
1 parent c04857c commit 8c8607d

File tree

2 files changed

+72
-19
lines changed

2 files changed

+72
-19
lines changed

lldb/include/lldb/Interpreter/CommandInterpreter.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,10 @@ class CommandInterpreter : public Broadcaster,
295295
StringList *matches = nullptr,
296296
StringList *descriptions = nullptr) const;
297297

298+
CommandObject *
299+
GetAliasCommandObject(llvm::StringRef cmd, StringList *matches = nullptr,
300+
StringList *descriptions = nullptr) const;
301+
298302
/// Determine whether a root level, built-in command with this name exists.
299303
bool CommandExists(llvm::StringRef cmd) const;
300304

lldb/source/Interpreter/CommandInterpreter.cpp

Lines changed: 68 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -520,10 +520,6 @@ void CommandInterpreter::Initialize() {
520520

521521
cmd_obj_sp = GetCommandSPExact("scripting run");
522522
if (cmd_obj_sp) {
523-
AddAlias("sc", cmd_obj_sp);
524-
AddAlias("scr", cmd_obj_sp);
525-
AddAlias("scri", cmd_obj_sp);
526-
AddAlias("scrip", cmd_obj_sp);
527523
AddAlias("script", cmd_obj_sp);
528524
}
529525

@@ -1302,6 +1298,36 @@ CommandObject *CommandInterpreter::GetUserCommandObject(
13021298
return {};
13031299
}
13041300

1301+
CommandObject *CommandInterpreter::GetAliasCommandObject(
1302+
llvm::StringRef cmd, StringList *matches, StringList *descriptions) const {
1303+
std::string cmd_str(cmd);
1304+
auto find_exact = [&](const CommandObject::CommandMap &map) {
1305+
auto found_elem = map.find(std::string(cmd));
1306+
if (found_elem == map.end())
1307+
return (CommandObject *)nullptr;
1308+
CommandObject *exact_cmd = found_elem->second.get();
1309+
if (exact_cmd) {
1310+
if (matches)
1311+
matches->AppendString(exact_cmd->GetCommandName());
1312+
if (descriptions)
1313+
descriptions->AppendString(exact_cmd->GetHelp());
1314+
return exact_cmd;
1315+
}
1316+
return (CommandObject *)nullptr;
1317+
};
1318+
1319+
CommandObject *exact_cmd = find_exact(GetAliases());
1320+
if (exact_cmd)
1321+
return exact_cmd;
1322+
1323+
// We didn't have an exact command, so now look for partial matches.
1324+
StringList tmp_list;
1325+
StringList *matches_ptr = matches ? matches : &tmp_list;
1326+
AddNamesMatchingPartialString(GetAliases(), cmd_str, *matches_ptr);
1327+
1328+
return {};
1329+
}
1330+
13051331
bool CommandInterpreter::CommandExists(llvm::StringRef cmd) const {
13061332
return m_command_dict.find(std::string(cmd)) != m_command_dict.end();
13071333
}
@@ -3421,6 +3447,19 @@ CommandInterpreter::ResolveCommandImpl(std::string &command_line,
34213447
std::string next_word;
34223448
StringList matches;
34233449
bool done = false;
3450+
3451+
auto build_alias_cmd = [&](std::string &full_name) {
3452+
revised_command_line.Clear();
3453+
matches.Clear();
3454+
std::string alias_result;
3455+
cmd_obj =
3456+
BuildAliasResult(full_name, scratch_command, alias_result, result);
3457+
revised_command_line.Printf("%s", alias_result.c_str());
3458+
if (cmd_obj) {
3459+
wants_raw_input = cmd_obj->WantsRawCommandString();
3460+
}
3461+
};
3462+
34243463
while (!done) {
34253464
char quote_char = '\0';
34263465
std::string suffix;
@@ -3432,14 +3471,7 @@ CommandInterpreter::ResolveCommandImpl(std::string &command_line,
34323471
bool is_real_command =
34333472
(!is_alias) || (cmd_obj != nullptr && !cmd_obj->IsAlias());
34343473
if (!is_real_command) {
3435-
matches.Clear();
3436-
std::string alias_result;
3437-
cmd_obj =
3438-
BuildAliasResult(full_name, scratch_command, alias_result, result);
3439-
revised_command_line.Printf("%s", alias_result.c_str());
3440-
if (cmd_obj) {
3441-
wants_raw_input = cmd_obj->WantsRawCommandString();
3442-
}
3474+
build_alias_cmd(full_name);
34433475
} else {
34443476
if (cmd_obj) {
34453477
llvm::StringRef cmd_name = cmd_obj->GetCommandName();
@@ -3486,21 +3518,38 @@ CommandInterpreter::ResolveCommandImpl(std::string &command_line,
34863518
if (cmd_obj == nullptr) {
34873519
const size_t num_matches = matches.GetSize();
34883520
if (matches.GetSize() > 1) {
3489-
StreamString error_msg;
3490-
error_msg.Printf("Ambiguous command '%s'. Possible matches:\n",
3491-
next_word.c_str());
3521+
StringList user_cmd_matches;
3522+
GetUserCommandObject(next_word, &user_cmd_matches);
3523+
3524+
StringList alias_matches;
3525+
GetAliasCommandObject(next_word, &alias_matches);
3526+
3527+
if (user_cmd_matches.GetSize() == 1) {
3528+
cmd_obj = GetCommandObject(user_cmd_matches.GetStringAtIndex(0));
3529+
done = static_cast<bool>(cmd_obj);
3530+
} else if (alias_matches.GetSize() == 1) {
3531+
std::string full_name;
3532+
GetAliasFullName(alias_matches.GetStringAtIndex(0), full_name);
3533+
build_alias_cmd(full_name);
3534+
done = static_cast<bool>(cmd_obj);
3535+
} else {
3536+
StreamString error_msg;
3537+
error_msg.Printf("Ambiguous command '%s'. Possible matches:\n",
3538+
next_word.c_str());
34923539

3493-
for (uint32_t i = 0; i < num_matches; ++i) {
3494-
error_msg.Printf("\t%s\n", matches.GetStringAtIndex(i));
3540+
for (uint32_t i = 0; i < num_matches; ++i) {
3541+
error_msg.Printf("\t%s\n", matches.GetStringAtIndex(i));
3542+
}
3543+
result.AppendRawError(error_msg.GetString());
34953544
}
3496-
result.AppendRawError(error_msg.GetString());
34973545
} else {
34983546
// We didn't have only one match, otherwise we wouldn't get here.
34993547
lldbassert(num_matches == 0);
35003548
result.AppendErrorWithFormat("'%s' is not a valid command.\n",
35013549
next_word.c_str());
35023550
}
3503-
return nullptr;
3551+
if (!done)
3552+
return nullptr;
35043553
}
35053554

35063555
if (cmd_obj->IsMultiwordObject()) {

0 commit comments

Comments
 (0)