diff options
author | Johnny Chen <johnny.chen@apple.com> | 2012-01-20 23:02:51 +0000 |
---|---|---|
committer | Johnny Chen <johnny.chen@apple.com> | 2012-01-20 23:02:51 +0000 |
commit | 98aceb08f8d4e44fd7c397ba80de8942a48d0fb8 (patch) | |
tree | c07c501cc418080e4f6888738012ced4bf606f94 /lldb | |
parent | 30398dd4108f8c5376e863ca665e29098f68db57 (diff) | |
download | bcm5719-llvm-98aceb08f8d4e44fd7c397ba80de8942a48d0fb8.tar.gz bcm5719-llvm-98aceb08f8d4e44fd7c397ba80de8942a48d0fb8.zip |
o CommandObjectSettingsSet.cpp:
Fix a bug where "settings set -r th" wouldn't complete.
o UserSettingsController.cpp:
Fix a bug where "settings set target.process." wouldn't complete.
o test/functionalities/completion:
Add various completion test cases related to 'settings set' command.
llvm-svn: 148596
Diffstat (limited to 'lldb')
-rw-r--r-- | lldb/source/Commands/CommandObjectSettings.cpp | 10 | ||||
-rw-r--r-- | lldb/source/Core/UserSettingsController.cpp | 28 | ||||
-rw-r--r-- | lldb/test/functionalities/completion/TestCompletion.py | 116 | ||||
-rw-r--r-- | lldb/test/lldbtest.py | 4 |
4 files changed, 144 insertions, 14 deletions
diff --git a/lldb/source/Commands/CommandObjectSettings.cpp b/lldb/source/Commands/CommandObjectSettings.cpp index 1a2ce9d835f..2a8b4247275 100644 --- a/lldb/source/Commands/CommandObjectSettings.cpp +++ b/lldb/source/Commands/CommandObjectSettings.cpp @@ -188,7 +188,11 @@ CommandObjectSettingsSet::HandleArgumentCompletion (Args &input, completion_str.erase (cursor_char_position); // Attempting to complete variable name - if (cursor_index == 1) + llvm::StringRef prev_str(cursor_index == 2 ? input.GetArgumentAtIndex(1) : ""); + if (cursor_index == 1 || + (cursor_index == 2 && prev_str.startswith("-")) // "settings set -r th", followed by Tab. + ) + { CommandCompletions::InvokeCommonCompletionCallbacks (m_interpreter, CommandCompletions::eSettingsNameCompletion, completion_str.c_str(), @@ -197,6 +201,10 @@ CommandObjectSettingsSet::HandleArgumentCompletion (Args &input, NULL, word_complete, matches); + // If there is only 1 match which fulfills the completion request, do an early return. + if (matches.GetSize() == 1 && completion_str.compare(matches.GetStringAtIndex(0)) != 0) + return 1; + } // Attempting to complete value if ((cursor_index == 2) // Partly into the variable's value diff --git a/lldb/source/Core/UserSettingsController.cpp b/lldb/source/Core/UserSettingsController.cpp index 65c263f396e..de3a71dd59e 100644 --- a/lldb/source/Core/UserSettingsController.cpp +++ b/lldb/source/Core/UserSettingsController.cpp @@ -1714,19 +1714,21 @@ UserSettingsController::CompleteSettingsNames (const UserSettingsControllerSP& u } + // The variable my_usc_sp keeps track of the user settings controller as + // we descend through the tree hierarchy. + UserSettingsControllerSP my_usc_sp = usc_sp; for (int i = 0; i < num_extra_levels; ++i) { ConstString child_level (partial_setting_name_pieces.GetArgumentAtIndex (0)); bool found = false; - int num_children = usc_sp->GetNumChildren(); - UserSettingsControllerSP child_usc_sp = usc_sp; + int num_children = my_usc_sp->GetNumChildren(); for (int j = 0; j < num_children && !found; ++j) { - if (child_usc_sp->GetChildAtIndex (j)->GetLevelName() == child_level) + if (my_usc_sp->GetChildAtIndex (j)->GetLevelName() == child_level) { found = true; - child_usc_sp = child_usc_sp->GetChildAtIndex (j); + my_usc_sp = my_usc_sp->GetChildAtIndex (j); partial_setting_name_pieces.Shift(); } } @@ -1750,15 +1752,15 @@ UserSettingsController::CompleteSettingsNames (const UserSettingsControllerSP& u // 'next_name' is an instance name. The last name piece must be a non-empty partial match against an // instance_name, assuming 'next_name' is valid. - if (usc_sp->IsLiveInstance (next_name)) + if (my_usc_sp->IsLiveInstance (next_name)) { std::string complete_prefix; - usc_sp->BuildParentPrefix (complete_prefix); + my_usc_sp->BuildParentPrefix (complete_prefix); - num_matches = usc_sp->InstanceVariableMatches(partial_setting_name_pieces.GetArgumentAtIndex(0), - complete_prefix, - next_name.c_str(), - matches); + num_matches = my_usc_sp->InstanceVariableMatches(partial_setting_name_pieces.GetArgumentAtIndex(0), + complete_prefix, + next_name.c_str(), + matches); word_complete = true; if (num_matches > 1) word_complete = false; @@ -1772,14 +1774,14 @@ UserSettingsController::CompleteSettingsNames (const UserSettingsControllerSP& u { // 'next_name' must be a child name. Find the correct child and pass the remaining piece to be resolved. bool found = false; - int num_children = usc_sp->GetNumChildren(); + int num_children = my_usc_sp->GetNumChildren(); ConstString child_level (next_name.c_str()); for (int i = 0; i < num_children; ++i) { - if (usc_sp->GetChildAtIndex (i)->GetLevelName() == child_level) + if (my_usc_sp->GetChildAtIndex (i)->GetLevelName() == child_level) { found = true; - return UserSettingsController::CompleteSettingsNames (usc_sp->GetChildAtIndex (i), + return UserSettingsController::CompleteSettingsNames (my_usc_sp->GetChildAtIndex (i), partial_setting_name_pieces, word_complete, matches); } diff --git a/lldb/test/functionalities/completion/TestCompletion.py b/lldb/test/functionalities/completion/TestCompletion.py new file mode 100644 index 00000000000..a6d2ce6d77f --- /dev/null +++ b/lldb/test/functionalities/completion/TestCompletion.py @@ -0,0 +1,116 @@ +""" +Test the lldb command line completion mechanism. +""" + +import os +import unittest2 +import lldb +import pexpect +from lldbtest import * + +class CommandLineCompletionTestCase(TestBase): + + mydir = os.path.join("functionalities", "completion") + + @classmethod + def classCleanup(cls): + """Cleanup the test byproducts.""" + system(["/bin/sh", "-c", "rm -f child_send.txt"]) + system(["/bin/sh", "-c", "rm -f child_read.txt"]) + + def test_settings_s(self): + """Test that 'settings s' completes to ['Available completions:', 'set', 'show'].""" + self.complete_from_to('settings s', ['Available completions:', 'set', 'show']) + + def test_settings_set_th(self): + """Test that 'settings set th' completes to 'settings set thread-format'.""" + self.complete_from_to('settings set th', 'settings set thread-format') + + def test_settings_s_dash(self): + """Test that 'settings set -' completes to ['Available completions:', '-n', '-r'].""" + self.complete_from_to('settings set -', ['Available completions:', '-n', '-r']) + + def test_settings_set_dash_r_th(self): + """Test that 'settings set -r th' completes to 'settings set -r thread-format'.""" + self.complete_from_to('settings set -r th', 'settings set -r thread-format') + + def test_settings_set_ta(self): + """Test that 'settings set ta' completes to 'settings set target.'.""" + self.complete_from_to('settings set ta', 'settings set target.') + + def test_settings_set_target_pr(self): + """Test that 'settings set target.pr' completes to ['Available completions:', + 'target.prefer-dynamic-value', 'target.process.'].""" + self.complete_from_to('settings set target.pr', + ['Available completions:', + 'target.prefer-dynamic-value', + 'target.process.']) + + def test_settings_set_target_process(self): + """Test that 'settings set target.process' completes to 'settings set target.process.'.""" + self.complete_from_to('settings set target.process', 'settings set target.process.') + + def test_settings_set_target_process_dot(self): + """Test that 'settings set target.process.' completes to 'settings set target.process.thread.'.""" + self.complete_from_to('settings set target.process.', 'settings set target.process.thread.') + + def test_settings_set_target_process_thread_dot(self): + """Test that 'settings set target.process.thread.' completes to ['Available completions:', + 'target.process.thread.step-avoid-regexp', 'target.process.thread.trace-thread'].""" + self.complete_from_to('settings set target.process.thread.', + ['Available completions:', + 'target.process.thread.step-avoid-regexp', + 'target.process.thread.trace-thread']) + + def complete_from_to(self, str_before, patterns): + """Test the completion mechanism completes str_before to pattern, where + patterns could be a pattern-string or a list of pattern-strings""" + prompt = "(lldb) " + add_prompt = "Enter your stop hook command(s). Type 'DONE' to end.\r\n> " + add_prompt1 = "\r\n> " + + # So that the child gets torn down after the test. + self.child = pexpect.spawn('%s %s' % (self.lldbHere, self.lldbOption)) + child = self.child + # Turn on logging for input/output to/from the child. + with open('child_send.txt', 'w') as f_send: + with open('child_read.txt', 'w') as f_read: + child.logfile_send = f_send + child.logfile_read = f_read + + # Test that str_before completes to str_after. + child.expect_exact(prompt) + child.setecho(True) + child.send("%s\t" % str_before) + #child.expect_exact("%s\t" % str_after) + child.sendline('') + child.expect_exact(prompt) + + with open('child_send.txt', 'r') as fs: + if self.TraceOn(): + print "\n\nContents of child_send.txt:" + print fs.read() + with open('child_read.txt', 'r') as fr: + from_child = fr.read() + if self.TraceOn(): + print "\n\nContents of child_read.txt:" + print from_child + + self.assertFalse(patterns is None) + if type(patterns) is not types.ListType: + patterns = [patterns] + + # If each pattern matches from_child, the completion mechanism works! + for p in patterns: + self.expect(from_child, msg=COMPLETIOND_MSG(str_before, p), exe=False, + patterns = [p]) + + child.logfile_send = None + child.logfile_read = None + + +if __name__ == '__main__': + import atexit + lldb.SBDebugger.Initialize() + atexit.register(lambda: lldb.SBDebugger.Terminate()) + unittest2.main() diff --git a/lldb/test/lldbtest.py b/lldb/test/lldbtest.py index becd3731c87..b6851e34b25 100644 --- a/lldb/test/lldbtest.py +++ b/lldb/test/lldbtest.py @@ -206,6 +206,10 @@ def CMD_MSG(str): '''A generic "Command '%s' returns successfully" message generator.''' return "Command '%s' returns successfully" % str +def COMPLETIOND_MSG(str_before, str_after): + '''A generic message generator for the completion mechanism.''' + return "'%s' successfully completes to '%s'" % (str_before, str_after) + def EXP_MSG(str, exe): '''A generic "'%s' returns expected result" message generator if exe. Otherwise, it generates "'%s' matches expected result" message.''' |