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