Index: lldb/trunk/include/lldb/Interpreter/Args.h =================================================================== --- lldb/trunk/include/lldb/Interpreter/Args.h +++ lldb/trunk/include/lldb/Interpreter/Args.h @@ -424,6 +424,9 @@ static void ExpandEscapedCharacters (const char *src, std::string &dst); + static std::string + EscapeLLDBCommandArgument (const std::string& arg, char quote_char); + // This one isn't really relevant to Arguments per se, but we're using the Args as a // general strings container, so... void Index: lldb/trunk/source/Interpreter/Args.cpp =================================================================== --- lldb/trunk/source/Interpreter/Args.cpp +++ lldb/trunk/source/Interpreter/Args.cpp @@ -1668,3 +1668,33 @@ } } +std::string +Args::EscapeLLDBCommandArgument (const std::string& arg, char quote_char) +{ + const char* chars_to_escape = nullptr; + switch (quote_char) + { + case '\0': + chars_to_escape = " \t\\'\"`"; + break; + case '\'': + chars_to_escape = ""; + break; + case '"': + chars_to_escape = "$\"`\\"; + break; + default: + assert(false && "Unhandled quote character"); + } + + std::string res; + res.reserve(arg.size()); + for (char c : arg) + { + if (::strchr(chars_to_escape, c)) + res.push_back('\\'); + res.push_back(c); + } + return res; +} + Index: lldb/trunk/source/Interpreter/CommandInterpreter.cpp =================================================================== --- lldb/trunk/source/Interpreter/CommandInterpreter.cpp +++ lldb/trunk/source/Interpreter/CommandInterpreter.cpp @@ -2002,7 +2002,7 @@ matches); if (num_command_matches <= 0) - return num_command_matches; + return num_command_matches; if (num_args == 0) { @@ -2021,18 +2021,18 @@ std::string common_prefix; matches.LongestCommonPrefix (common_prefix); 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 (num_command_matches == 1 && word_complete) { char quote_char = parsed_line.GetArgumentQuoteCharAtIndex(cursor_index); + common_prefix = Args::EscapeLLDBCommandArgument(common_prefix, quote_char); if (quote_char != '\0') common_prefix.push_back(quote_char); - common_prefix.push_back(' '); } - common_prefix.erase (0, partial_name_len); matches.InsertStringAtIndex(0, common_prefix.c_str()); } return num_command_matches; Index: lldb/trunk/test/functionalities/completion/Makefile =================================================================== --- lldb/trunk/test/functionalities/completion/Makefile +++ lldb/trunk/test/functionalities/completion/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules Index: lldb/trunk/test/functionalities/completion/TestCompletion.py =================================================================== --- lldb/trunk/test/functionalities/completion/TestCompletion.py +++ lldb/trunk/test/functionalities/completion/TestCompletion.py @@ -219,6 +219,23 @@ """Test that 'target va' completes to 'target variable '.""" self.complete_from_to('target va', 'target variable ') + @skipUnlessDarwin + @dsym_test + def test_symbol_name_dsym(self): + self.buildDsym() + self.complete_from_to('''file a.out + breakpoint set -n Fo''', + 'breakpoint set -n Foo::Bar(int,\\ int)', + turn_off_re_match=True) + + @dwarf_test + def test_symbol_name_dwarf(self): + self.buildDwarf() + self.complete_from_to('''file a.out + breakpoint set -n Fo''', + 'breakpoint set -n Foo::Bar(int,\\ int)', + turn_off_re_match=True) + def complete_from_to(self, str_input, patterns, turn_off_re_match=False): """Test that the completion mechanism completes str_input to patterns, where patterns could be a pattern-string or a list of pattern-strings""" Index: lldb/trunk/test/functionalities/completion/main.cpp =================================================================== --- lldb/trunk/test/functionalities/completion/main.cpp +++ lldb/trunk/test/functionalities/completion/main.cpp @@ -0,0 +1,14 @@ +class Foo +{ +public: + int Bar(int x, int y) + { + return x + y; + } +}; + +int main() +{ + Foo f; + f.Bar(1, 2); +}