blob: c33120c66b7f400a98a631f3336e8307b1b198f5 [file] [log] [blame]
"""
Test the lldb command line completion mechanism for the 'expr' command.
"""
from __future__ import print_function
import random
import os
import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbplatform
from lldbsuite.test import lldbutil
class CommandLineExprCompletionTestCase(TestBase):
mydir = TestBase.compute_mydir(__file__)
NO_DEBUG_INFO_TESTCASE = True
@expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24489")
def test_expr_completion(self):
self.build()
self.main_source = "main.cpp"
self.main_source_spec = lldb.SBFileSpec(self.main_source)
self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
# Try the completion before we have a context to complete on.
self.assume_no_completions('expr some_expr')
self.assume_no_completions('expr ')
self.assume_no_completions('expr f')
(target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self,
'// Break here', self.main_source_spec)
# Completing member functions
self.complete_exactly('expr some_expr.FooNoArgs',
'expr some_expr.FooNoArgsBar()')
self.complete_exactly('expr some_expr.FooWithArgs',
'expr some_expr.FooWithArgsBar(')
self.complete_exactly('expr some_expr.FooWithMultipleArgs',
'expr some_expr.FooWithMultipleArgsBar(')
self.complete_exactly('expr some_expr.FooUnderscore',
'expr some_expr.FooUnderscoreBar_()')
self.complete_exactly('expr some_expr.FooNumbers',
'expr some_expr.FooNumbersBar1()')
self.complete_exactly('expr some_expr.StaticMemberMethod',
'expr some_expr.StaticMemberMethodBar()')
# Completing static functions
self.complete_exactly('expr Expr::StaticMemberMethod',
'expr Expr::StaticMemberMethodBar()')
# Completing member variables
self.complete_exactly('expr some_expr.MemberVariab',
'expr some_expr.MemberVariableBar')
# Multiple completions
self.completions_contain('expr some_expr.',
['some_expr.FooNumbersBar1()',
'some_expr.FooUnderscoreBar_()',
'some_expr.FooWithArgsBar(',
'some_expr.MemberVariableBar'])
self.completions_contain('expr some_expr.Foo',
['some_expr.FooNumbersBar1()',
'some_expr.FooUnderscoreBar_()',
'some_expr.FooWithArgsBar('])
self.completions_contain('expr ',
['static_cast',
'reinterpret_cast',
'dynamic_cast'])
self.completions_contain('expr 1 + ',
['static_cast',
'reinterpret_cast',
'dynamic_cast'])
# Completion expr without spaces
# This is a bit awkward looking for the user, but that's how
# the completion API works at the moment.
self.completions_contain('expr 1+',
['1+some_expr', "1+static_cast"])
# Test with spaces
self.complete_exactly('expr some_expr .FooNoArgs',
'expr some_expr .FooNoArgsBar()')
self.complete_exactly('expr some_expr .FooNoArgs',
'expr some_expr .FooNoArgsBar()')
self.complete_exactly('expr some_expr .FooNoArgs',
'expr some_expr .FooNoArgsBar()')
self.complete_exactly('expr some_expr. FooNoArgs',
'expr some_expr. FooNoArgsBar()')
self.complete_exactly('expr some_expr . FooNoArgs',
'expr some_expr . FooNoArgsBar()')
self.complete_exactly('expr Expr :: StaticMemberMethod',
'expr Expr :: StaticMemberMethodBar()')
self.complete_exactly('expr Expr ::StaticMemberMethod',
'expr Expr ::StaticMemberMethodBar()')
self.complete_exactly('expr Expr:: StaticMemberMethod',
'expr Expr:: StaticMemberMethodBar()')
# Test that string literals don't break our parsing logic.
self.complete_exactly('expr const char *cstr = "some_e"; char c = *cst',
'expr const char *cstr = "some_e"; char c = *cstr')
self.complete_exactly('expr const char *cstr = "some_e" ; char c = *cst',
'expr const char *cstr = "some_e" ; char c = *cstr')
# Requesting completions inside an incomplete string doesn't provide any
# completions.
self.complete_exactly('expr const char *cstr = "some_e',
'expr const char *cstr = "some_e')
# Completing inside double dash should do nothing
self.assume_no_completions('expr -i0 -- some_expr.', 10)
self.assume_no_completions('expr -i0 -- some_expr.', 11)
# Test with expr arguments
self.complete_exactly('expr -i0 -- some_expr .FooNoArgs',
'expr -i0 -- some_expr .FooNoArgsBar()')
self.complete_exactly('expr -i0 -- some_expr .FooNoArgs',
'expr -i0 -- some_expr .FooNoArgsBar()')
# Addrof and deref
self.complete_exactly('expr (*(&some_expr)).FooNoArgs',
'expr (*(&some_expr)).FooNoArgsBar()')
self.complete_exactly('expr (*(&some_expr)) .FooNoArgs',
'expr (*(&some_expr)) .FooNoArgsBar()')
self.complete_exactly('expr (* (&some_expr)) .FooNoArgs',
'expr (* (&some_expr)) .FooNoArgsBar()')
self.complete_exactly('expr (* (& some_expr)) .FooNoArgs',
'expr (* (& some_expr)) .FooNoArgsBar()')
# Addrof and deref (part 2)
self.complete_exactly('expr (&some_expr)->FooNoArgs',
'expr (&some_expr)->FooNoArgsBar()')
self.complete_exactly('expr (&some_expr) ->FooNoArgs',
'expr (&some_expr) ->FooNoArgsBar()')
self.complete_exactly('expr (&some_expr) -> FooNoArgs',
'expr (&some_expr) -> FooNoArgsBar()')
self.complete_exactly('expr (&some_expr)-> FooNoArgs',
'expr (&some_expr)-> FooNoArgsBar()')
# Builtin arg
self.complete_exactly('expr static_ca',
'expr static_cast')
# From other files
self.complete_exactly('expr fwd_decl_ptr->Hidden',
'expr fwd_decl_ptr->HiddenMember')
# Types
self.complete_exactly('expr LongClassNa',
'expr LongClassName')
self.complete_exactly('expr LongNamespaceName::NestedCla',
'expr LongNamespaceName::NestedClass')
# Namespaces
self.complete_exactly('expr LongNamespaceNa',
'expr LongNamespaceName::')
# Multiple arguments
self.complete_exactly('expr &some_expr + &some_e',
'expr &some_expr + &some_expr')
self.complete_exactly('expr SomeLongVarNameWithCapitals + SomeLongVarName',
'expr SomeLongVarNameWithCapitals + SomeLongVarNameWithCapitals')
self.complete_exactly('expr SomeIntVar + SomeIntV',
'expr SomeIntVar + SomeIntVar')
# Multiple statements
self.complete_exactly('expr long LocalVariable = 0; LocalVaria',
'expr long LocalVariable = 0; LocalVariable')
# Custom Decls
self.complete_exactly('expr auto l = [](int LeftHandSide, int bx){ return LeftHandS',
'expr auto l = [](int LeftHandSide, int bx){ return LeftHandSide')
self.complete_exactly('expr struct LocalStruct { long MemberName; } ; LocalStruct S; S.Mem',
'expr struct LocalStruct { long MemberName; } ; LocalStruct S; S.MemberName')
# Completing function call arguments
self.complete_exactly('expr some_expr.FooWithArgsBar(some_exp',
'expr some_expr.FooWithArgsBar(some_expr')
self.complete_exactly('expr some_expr.FooWithArgsBar(SomeIntV',
'expr some_expr.FooWithArgsBar(SomeIntVar')
self.complete_exactly('expr some_expr.FooWithMultipleArgsBar(SomeIntVar, SomeIntVa',
'expr some_expr.FooWithMultipleArgsBar(SomeIntVar, SomeIntVar')
# Function return values
self.complete_exactly('expr some_expr.Self().FooNoArgs',
'expr some_expr.Self().FooNoArgsBar()')
self.complete_exactly('expr some_expr.Self() .FooNoArgs',
'expr some_expr.Self() .FooNoArgsBar()')
self.complete_exactly('expr some_expr.Self(). FooNoArgs',
'expr some_expr.Self(). FooNoArgsBar()')
@expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24489")
def test_expr_completion_with_descriptions(self):
self.build()
self.main_source = "main.cpp"
self.main_source_spec = lldb.SBFileSpec(self.main_source)
self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
(target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self,
'// Break here', self.main_source_spec)
self.check_completion_with_desc("expr ", [
# VarDecls have their type as description.
["some_expr", "Expr &"],
# builtin types have no description.
["int", ""],
["float", ""]
])
self.check_completion_with_desc("expr some_expr.", [
# Functions have their signature as description.
["some_expr.Self()", "Expr &Self()"],
["some_expr.operator=(", "inline Expr &operator=(const Expr &)"],
["some_expr.FooNumbersBar1()", "int FooNumbersBar1()"],
["some_expr.StaticMemberMethodBar()", "static int StaticMemberMethodBar()"],
["some_expr.FooWithArgsBar(", "int FooWithArgsBar(int)"],
["some_expr.FooNoArgsBar()", "int FooNoArgsBar()"],
["some_expr.FooUnderscoreBar_()", "int FooUnderscoreBar_()"],
["some_expr.FooWithMultipleArgsBar(", "int FooWithMultipleArgsBar(int, int)"],
["some_expr.~Expr()", "inline ~Expr()"],
# FieldDecls have their type as description.
["some_expr.MemberVariableBar", "int"],
])
def assume_no_completions(self, str_input, cursor_pos = None):
interp = self.dbg.GetCommandInterpreter()
match_strings = lldb.SBStringList()
if cursor_pos is None:
cursor_pos = len(str_input)
num_matches = interp.HandleCompletion(str_input, cursor_pos, 0, -1, match_strings)
available_completions = []
for m in match_strings:
available_completions.append(m)
self.assertEquals(num_matches, 0, "Got matches, but didn't expect any: " + str(available_completions))
def completions_contain(self, str_input, items):
interp = self.dbg.GetCommandInterpreter()
match_strings = lldb.SBStringList()
num_matches = interp.HandleCompletion(str_input, len(str_input), 0, -1, match_strings)
common_match = match_strings.GetStringAtIndex(0)
for item in items:
found = False
for m in match_strings:
if m == item:
found = True
if not found:
# Transform match_strings to a python list with strings
available_completions = []
for m in match_strings:
available_completions.append(m)
self.assertTrue(found, "Couldn't find completion " + item + " in completions " + str(available_completions))