1"""
2Test the lldb command line completion mechanism for the 'expr' command.
3"""
4
5
6import lldb
7from lldbsuite.test.decorators import *
8from lldbsuite.test.lldbtest import *
9from lldbsuite.test import lldbplatform
10from lldbsuite.test import lldbutil
11
12class CommandLineExprCompletionTestCase(TestBase):
13
14    mydir = TestBase.compute_mydir(__file__)
15
16    NO_DEBUG_INFO_TESTCASE = True
17
18    def test_expr_completion(self):
19        self.build()
20        self.main_source = "main.cpp"
21        self.main_source_spec = lldb.SBFileSpec(self.main_source)
22        self.createTestTarget()
23
24        # Try the completion before we have a context to complete on.
25        self.assume_no_completions('expr some_expr')
26        self.assume_no_completions('expr ')
27        self.assume_no_completions('expr f')
28
29
30        (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self,
31                                          '// Break here', self.main_source_spec)
32
33        # Completing member functions
34        self.complete_exactly('expr some_expr.FooNoArgs',
35                              'expr some_expr.FooNoArgsBar()')
36        self.complete_exactly('expr some_expr.FooWithArgs',
37                              'expr some_expr.FooWithArgsBar(')
38        self.complete_exactly('expr some_expr.FooWithMultipleArgs',
39                              'expr some_expr.FooWithMultipleArgsBar(')
40        self.complete_exactly('expr some_expr.FooUnderscore',
41                              'expr some_expr.FooUnderscoreBar_()')
42        self.complete_exactly('expr some_expr.FooNumbers',
43                              'expr some_expr.FooNumbersBar1()')
44        self.complete_exactly('expr some_expr.StaticMemberMethod',
45                              'expr some_expr.StaticMemberMethodBar()')
46
47        # Completing static functions
48        self.complete_exactly('expr Expr::StaticMemberMethod',
49                              'expr Expr::StaticMemberMethodBar()')
50
51        # Completing member variables
52        self.complete_exactly('expr some_expr.MemberVariab',
53                              'expr some_expr.MemberVariableBar')
54
55        # Multiple completions
56        self.completions_contain('expr some_expr.',
57                                 ['some_expr.FooNumbersBar1()',
58                                  'some_expr.FooUnderscoreBar_()',
59                                  'some_expr.FooWithArgsBar(',
60                                  'some_expr.MemberVariableBar'])
61
62        self.completions_contain('expr some_expr.Foo',
63                                 ['some_expr.FooNumbersBar1()',
64                                  'some_expr.FooUnderscoreBar_()',
65                                  'some_expr.FooWithArgsBar('])
66
67        self.completions_contain('expr ',
68                                 ['static_cast',
69                                  'reinterpret_cast',
70                                  'dynamic_cast'])
71
72        self.completions_contain('expr 1 + ',
73                                 ['static_cast',
74                                  'reinterpret_cast',
75                                  'dynamic_cast'])
76
77        # Completion expr without spaces
78        # This is a bit awkward looking for the user, but that's how
79        # the completion API works at the moment.
80        self.completions_contain('expr 1+',
81                                 ['1+some_expr', "1+static_cast"])
82
83        # Test with spaces
84        self.complete_exactly('expr   some_expr .FooNoArgs',
85                              'expr   some_expr .FooNoArgsBar()')
86        self.complete_exactly('expr  some_expr .FooNoArgs',
87                              'expr  some_expr .FooNoArgsBar()')
88        self.complete_exactly('expr some_expr .FooNoArgs',
89                              'expr some_expr .FooNoArgsBar()')
90        self.complete_exactly('expr some_expr. FooNoArgs',
91                              'expr some_expr. FooNoArgsBar()')
92        self.complete_exactly('expr some_expr . FooNoArgs',
93                              'expr some_expr . FooNoArgsBar()')
94        self.complete_exactly('expr Expr :: StaticMemberMethod',
95                              'expr Expr :: StaticMemberMethodBar()')
96        self.complete_exactly('expr Expr ::StaticMemberMethod',
97                              'expr Expr ::StaticMemberMethodBar()')
98        self.complete_exactly('expr Expr:: StaticMemberMethod',
99                              'expr Expr:: StaticMemberMethodBar()')
100
101        # Test that string literals don't break our parsing logic.
102        self.complete_exactly('expr const char *cstr = "some_e"; char c = *cst',
103                              'expr const char *cstr = "some_e"; char c = *cstr')
104        self.complete_exactly('expr const char *cstr = "some_e" ; char c = *cst',
105                              'expr const char *cstr = "some_e" ; char c = *cstr')
106        # Requesting completions inside an incomplete string doesn't provide any
107        # completions.
108        self.complete_exactly('expr const char *cstr = "some_e',
109                              'expr const char *cstr = "some_e')
110
111        # Completing inside double dash should do nothing
112        self.assume_no_completions('expr -i0 -- some_expr.', 10)
113        self.assume_no_completions('expr -i0 -- some_expr.', 11)
114
115        # Test with expr arguments
116        self.complete_exactly('expr -i0 -- some_expr .FooNoArgs',
117                              'expr -i0 -- some_expr .FooNoArgsBar()')
118        self.complete_exactly('expr  -i0 -- some_expr .FooNoArgs',
119                              'expr  -i0 -- some_expr .FooNoArgsBar()')
120
121        # Addrof and deref
122        self.complete_exactly('expr (*(&some_expr)).FooNoArgs',
123                              'expr (*(&some_expr)).FooNoArgsBar()')
124        self.complete_exactly('expr (*(&some_expr)) .FooNoArgs',
125                              'expr (*(&some_expr)) .FooNoArgsBar()')
126        self.complete_exactly('expr (* (&some_expr)) .FooNoArgs',
127                              'expr (* (&some_expr)) .FooNoArgsBar()')
128        self.complete_exactly('expr (* (& some_expr)) .FooNoArgs',
129                              'expr (* (& some_expr)) .FooNoArgsBar()')
130
131        # Addrof and deref (part 2)
132        self.complete_exactly('expr (&some_expr)->FooNoArgs',
133                              'expr (&some_expr)->FooNoArgsBar()')
134        self.complete_exactly('expr (&some_expr) ->FooNoArgs',
135                              'expr (&some_expr) ->FooNoArgsBar()')
136        self.complete_exactly('expr (&some_expr) -> FooNoArgs',
137                              'expr (&some_expr) -> FooNoArgsBar()')
138        self.complete_exactly('expr (&some_expr)-> FooNoArgs',
139                              'expr (&some_expr)-> FooNoArgsBar()')
140
141        # Builtin arg
142        self.complete_exactly('expr static_ca',
143                              'expr static_cast')
144
145        # From other files
146        self.complete_exactly('expr fwd_decl_ptr->Hidden',
147                              'expr fwd_decl_ptr->HiddenMember')
148
149
150        # Types
151        self.complete_exactly('expr LongClassNa',
152                              'expr LongClassName')
153        self.complete_exactly('expr LongNamespaceName::NestedCla',
154                              'expr LongNamespaceName::NestedClass')
155
156        # Namespaces
157        self.complete_exactly('expr LongNamespaceNa',
158                              'expr LongNamespaceName::')
159
160        # Multiple arguments
161        self.complete_exactly('expr &some_expr + &some_e',
162                              'expr &some_expr + &some_expr')
163        self.complete_exactly('expr SomeLongVarNameWithCapitals + SomeLongVarName',
164                              'expr SomeLongVarNameWithCapitals + SomeLongVarNameWithCapitals')
165        self.complete_exactly('expr SomeIntVar + SomeIntV',
166                              'expr SomeIntVar + SomeIntVar')
167
168        # Multiple statements
169        self.complete_exactly('expr long LocalVariable = 0; LocalVaria',
170                              'expr long LocalVariable = 0; LocalVariable')
171
172        # Custom Decls
173        self.complete_exactly('expr auto l = [](int LeftHandSide, int bx){ return LeftHandS',
174                              'expr auto l = [](int LeftHandSide, int bx){ return LeftHandSide')
175        self.complete_exactly('expr struct LocalStruct { long MemberName; } ; LocalStruct S; S.Mem',
176                              'expr struct LocalStruct { long MemberName; } ; LocalStruct S; S.MemberName')
177
178        # Completing function call arguments
179        self.complete_exactly('expr some_expr.FooWithArgsBar(some_exp',
180                              'expr some_expr.FooWithArgsBar(some_expr')
181        self.complete_exactly('expr some_expr.FooWithArgsBar(SomeIntV',
182                              'expr some_expr.FooWithArgsBar(SomeIntVar')
183        self.complete_exactly('expr some_expr.FooWithMultipleArgsBar(SomeIntVar, SomeIntVa',
184                              'expr some_expr.FooWithMultipleArgsBar(SomeIntVar, SomeIntVar')
185
186        # Function return values
187        self.complete_exactly('expr some_expr.Self().FooNoArgs',
188                              'expr some_expr.Self().FooNoArgsBar()')
189        self.complete_exactly('expr some_expr.Self() .FooNoArgs',
190                              'expr some_expr.Self() .FooNoArgsBar()')
191        self.complete_exactly('expr some_expr.Self(). FooNoArgs',
192                              'expr some_expr.Self(). FooNoArgsBar()')
193
194    def test_expr_completion_with_descriptions(self):
195        self.build()
196        self.main_source = "main.cpp"
197        self.main_source_spec = lldb.SBFileSpec(self.main_source)
198        self.createTestTarget()
199
200        (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self,
201                                          '// Break here', self.main_source_spec)
202
203        self.check_completion_with_desc("expr ", [
204            # builtin types have no description.
205            ["int", ""],
206            ["float", ""],
207            # VarDecls have their type as description.
208            ["some_expr", "Expr &"],
209        ], enforce_order = True)
210        self.check_completion_with_desc("expr some_expr.", [
211            # Functions have their signature as description.
212            ["some_expr.~Expr()", "inline ~Expr()"],
213            ["some_expr.operator=(", "inline Expr &operator=(const Expr &)"],
214            # FieldDecls have their type as description.
215            ["some_expr.MemberVariableBar", "int"],
216            ["some_expr.StaticMemberMethodBar()", "static int StaticMemberMethodBar()"],
217            ["some_expr.Self()", "Expr &Self()"],
218            ["some_expr.FooNoArgsBar()", "int FooNoArgsBar()"],
219            ["some_expr.FooWithArgsBar(", "int FooWithArgsBar(int)"],
220            ["some_expr.FooNumbersBar1()", "int FooNumbersBar1()"],
221            ["some_expr.FooUnderscoreBar_()", "int FooUnderscoreBar_()"],
222            ["some_expr.FooWithMultipleArgsBar(", "int FooWithMultipleArgsBar(int, int)"],
223        ], enforce_order = True)
224
225    def assume_no_completions(self, str_input, cursor_pos = None):
226        interp = self.dbg.GetCommandInterpreter()
227        match_strings = lldb.SBStringList()
228        if cursor_pos is None:
229          cursor_pos = len(str_input)
230        num_matches = interp.HandleCompletion(str_input, cursor_pos, 0, -1, match_strings)
231
232        available_completions = []
233        for m in match_strings:
234            available_completions.append(m)
235
236        self.assertEquals(num_matches, 0, "Got matches, but didn't expect any: " + str(available_completions))
237
238    def completions_contain(self, str_input, items):
239        interp = self.dbg.GetCommandInterpreter()
240        match_strings = lldb.SBStringList()
241        num_matches = interp.HandleCompletion(str_input, len(str_input), 0, -1, match_strings)
242        common_match = match_strings.GetStringAtIndex(0)
243
244        for item in items:
245            found = False
246            for m in match_strings:
247                if m == item:
248                    found = True
249            if not found:
250                # Transform match_strings to a python list with strings
251                available_completions = []
252                for m in match_strings:
253                     available_completions.append(m)
254                self.assertTrue(found, "Couldn't find completion " + item + " in completions " + str(available_completions))
255