blob: 5f0d494443fd60a24ee7e12d1aad3dca263b14c2 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- CommandCompletions.cpp ----------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Chris Lattner30fdc8d2010-06-08 16:52:24 +000010// C Includes
Jim Ingham558ce122010-06-30 05:02:46 +000011#include <sys/stat.h>
Greg Claytonfd184262011-02-05 02:27:52 +000012#if defined(__APPLE__) || defined(__linux__)
Jim Ingham7cc478b2010-07-02 00:45:55 +000013#include <pwd.h>
Greg Claytonfd184262011-02-05 02:27:52 +000014#endif
Jim Ingham558ce122010-06-30 05:02:46 +000015
Chris Lattner30fdc8d2010-06-08 16:52:24 +000016// C++ Includes
17// Other libraries and framework includes
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +000018#include "llvm/ADT/SmallString.h"
Zachary Turner2cc5a182017-03-13 00:41:01 +000019#include "llvm/ADT/StringSet.h"
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +000020
Chris Lattner30fdc8d2010-06-08 16:52:24 +000021// Project includes
Greg Clayton9b62fd22011-02-01 05:15:22 +000022#include "lldb/Core/FileSpecList.h"
Greg Clayton1f746072012-08-29 21:13:06 +000023#include "lldb/Core/Module.h"
Zachary Turner190fadc2016-03-22 17:58:09 +000024#include "lldb/Core/PluginManager.h"
Zachary Turner190fadc2016-03-22 17:58:09 +000025#include "lldb/Host/FileSystem.h"
Greg Clayton9b62fd22011-02-01 05:15:22 +000026#include "lldb/Interpreter/Args.h"
27#include "lldb/Interpreter/CommandCompletions.h"
28#include "lldb/Interpreter/CommandInterpreter.h"
Zachary Turner633a29c2015-03-04 01:58:01 +000029#include "lldb/Interpreter/OptionValueProperties.h"
Greg Clayton1f746072012-08-29 21:13:06 +000030#include "lldb/Symbol/CompileUnit.h"
Greg Claytonf21fead2013-05-14 23:43:18 +000031#include "lldb/Symbol/Variable.h"
Greg Clayton9b62fd22011-02-01 05:15:22 +000032#include "lldb/Target/Target.h"
33#include "lldb/Utility/CleanUp.h"
Zachary Turner5713a052017-03-22 18:40:07 +000034#include "lldb/Utility/FileSpec.h"
Zachary Turner2f3df612017-04-06 21:28:29 +000035#include "lldb/Utility/StreamString.h"
Zachary Turner2cc5a182017-03-13 00:41:01 +000036#include "lldb/Utility/TildeExpressionResolver.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000037
Zachary Turner190fadc2016-03-22 17:58:09 +000038#include "llvm/ADT/SmallString.h"
Zachary Turner7d86ee52017-03-08 17:56:08 +000039#include "llvm/Support/FileSystem.h"
Zachary Turner2cc5a182017-03-13 00:41:01 +000040#include "llvm/Support/Path.h"
Zachary Turner190fadc2016-03-22 17:58:09 +000041
Chris Lattner30fdc8d2010-06-08 16:52:24 +000042using namespace lldb_private;
43
44CommandCompletions::CommonCompletionElement
Kate Stoneb9c1b512016-09-06 20:57:50 +000045 CommandCompletions::g_common_completions[] = {
46 {eCustomCompletion, nullptr},
47 {eSourceFileCompletion, CommandCompletions::SourceFiles},
48 {eDiskFileCompletion, CommandCompletions::DiskFiles},
49 {eDiskDirectoryCompletion, CommandCompletions::DiskDirectories},
50 {eSymbolCompletion, CommandCompletions::Symbols},
51 {eModuleCompletion, CommandCompletions::Modules},
52 {eSettingsNameCompletion, CommandCompletions::SettingsNames},
53 {ePlatformPluginCompletion, CommandCompletions::PlatformPluginNames},
54 {eArchitectureCompletion, CommandCompletions::ArchitectureNames},
55 {eVariablePathCompletion, CommandCompletions::VariablePath},
56 {eNoCompletion, nullptr} // This one has to be last in the list.
Chris Lattner30fdc8d2010-06-08 16:52:24 +000057};
58
Kate Stoneb9c1b512016-09-06 20:57:50 +000059bool CommandCompletions::InvokeCommonCompletionCallbacks(
60 CommandInterpreter &interpreter, uint32_t completion_mask,
Zachary Turner4aa87532016-11-17 01:37:42 +000061 llvm::StringRef completion_str, int match_start_point,
62 int max_return_elements, SearchFilter *searcher, bool &word_complete,
63 StringList &matches) {
Kate Stoneb9c1b512016-09-06 20:57:50 +000064 bool handled = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000065
Kate Stoneb9c1b512016-09-06 20:57:50 +000066 if (completion_mask & eCustomCompletion)
67 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000068
Kate Stoneb9c1b512016-09-06 20:57:50 +000069 for (int i = 0;; i++) {
70 if (g_common_completions[i].type == eNoCompletion)
71 break;
72 else if ((g_common_completions[i].type & completion_mask) ==
73 g_common_completions[i].type &&
74 g_common_completions[i].callback != nullptr) {
75 handled = true;
76 g_common_completions[i].callback(interpreter, completion_str,
77 match_start_point, max_return_elements,
78 searcher, word_complete, matches);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000079 }
Kate Stoneb9c1b512016-09-06 20:57:50 +000080 }
81 return handled;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000082}
83
Kate Stoneb9c1b512016-09-06 20:57:50 +000084int CommandCompletions::SourceFiles(CommandInterpreter &interpreter,
Zachary Turner4aa87532016-11-17 01:37:42 +000085 llvm::StringRef partial_file_name,
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +000086 int match_start_point,
87 int max_return_elements,
Kate Stoneb9c1b512016-09-06 20:57:50 +000088 SearchFilter *searcher, bool &word_complete,
89 StringList &matches) {
90 word_complete = true;
91 // Find some way to switch "include support files..."
92 SourceFileCompleter completer(interpreter, false, partial_file_name,
93 match_start_point, max_return_elements,
94 matches);
95
96 if (searcher == nullptr) {
97 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
98 SearchFilterForUnconstrainedSearches null_searcher(target_sp);
99 completer.DoCompletion(&null_searcher);
100 } else {
101 completer.DoCompletion(searcher);
102 }
103 return matches.GetSize();
Jim Ingham558ce122010-06-30 05:02:46 +0000104}
105
Zachary Turner2cc5a182017-03-13 00:41:01 +0000106static int DiskFilesOrDirectories(const llvm::Twine &partial_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000107 bool only_directories, bool &saw_directory,
Zachary Turner2cc5a182017-03-13 00:41:01 +0000108 StringList &matches,
109 TildeExpressionResolver &Resolver) {
110 matches.Clear();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000111
Zachary Turner2cc5a182017-03-13 00:41:01 +0000112 llvm::SmallString<256> CompletionBuffer;
113 llvm::SmallString<256> Storage;
114 partial_name.toVector(CompletionBuffer);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000115
Zachary Turner2cc5a182017-03-13 00:41:01 +0000116 if (CompletionBuffer.size() >= PATH_MAX)
117 return 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000118
Zachary Turner2cc5a182017-03-13 00:41:01 +0000119 namespace fs = llvm::sys::fs;
120 namespace path = llvm::sys::path;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000121
Zachary Turner2cc5a182017-03-13 00:41:01 +0000122 llvm::StringRef SearchDir;
123 llvm::StringRef PartialItem;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000124
Zachary Turner2cc5a182017-03-13 00:41:01 +0000125 if (CompletionBuffer.startswith("~")) {
126 llvm::StringRef Buffer(CompletionBuffer);
Zachary Turner5c5091f2017-03-16 22:28:04 +0000127 size_t FirstSep =
128 Buffer.find_if([](char c) { return path::is_separator(c); });
Kate Stoneb9c1b512016-09-06 20:57:50 +0000129
Zachary Turner2cc5a182017-03-13 00:41:01 +0000130 llvm::StringRef Username = Buffer.take_front(FirstSep);
131 llvm::StringRef Remainder;
132 if (FirstSep != llvm::StringRef::npos)
133 Remainder = Buffer.drop_front(FirstSep + 1);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000134
Zachary Turner2cc5a182017-03-13 00:41:01 +0000135 llvm::SmallString<PATH_MAX> Resolved;
136 if (!Resolver.ResolveExact(Username, Resolved)) {
137 // We couldn't resolve it as a full username. If there were no slashes
138 // then this might be a partial username. We try to resolve it as such
139 // but after that, we're done regardless of any matches.
140 if (FirstSep == llvm::StringRef::npos) {
141 llvm::StringSet<> MatchSet;
142 saw_directory = Resolver.ResolvePartial(Username, MatchSet);
143 for (const auto &S : MatchSet) {
144 Resolved = S.getKey();
145 path::append(Resolved, path::get_separator());
146 matches.AppendString(Resolved);
147 }
148 saw_directory = (matches.GetSize() > 0);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000149 }
Zachary Turner0734e6a2017-03-12 20:01:37 +0000150 return matches.GetSize();
Zachary Turner2cc5a182017-03-13 00:41:01 +0000151 }
152
153 // If there was no trailing slash, then we're done as soon as we resolve the
154 // expression to the correct directory. Otherwise we need to continue
155 // looking for matches within that directory.
156 if (FirstSep == llvm::StringRef::npos) {
157 // Make sure it ends with a separator.
158 path::append(CompletionBuffer, path::get_separator());
159 saw_directory = true;
160 matches.AppendString(CompletionBuffer);
161 return 1;
162 }
163
164 // We want to keep the form the user typed, so we special case this to
165 // search in the fully resolved directory, but CompletionBuffer keeps the
166 // unmodified form that the user typed.
167 Storage = Resolved;
168 SearchDir = Resolved;
169 } else {
170 SearchDir = path::parent_path(CompletionBuffer);
Zachary Turnerd5bd3a12017-03-12 18:18:50 +0000171 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000172
Zachary Turner2cc5a182017-03-13 00:41:01 +0000173 size_t FullPrefixLen = CompletionBuffer.size();
Zachary Turner0734e6a2017-03-12 20:01:37 +0000174
Zachary Turner2cc5a182017-03-13 00:41:01 +0000175 PartialItem = path::filename(CompletionBuffer);
176 if (PartialItem == ".")
177 PartialItem = llvm::StringRef();
Zachary Turner0734e6a2017-03-12 20:01:37 +0000178
Zachary Turner2cc5a182017-03-13 00:41:01 +0000179 assert(!SearchDir.empty());
180 assert(!PartialItem.contains(path::get_separator()));
Zachary Turner0734e6a2017-03-12 20:01:37 +0000181
Zachary Turner2cc5a182017-03-13 00:41:01 +0000182 // SearchDir now contains the directory to search in, and Prefix contains the
183 // text we want to match against items in that directory.
184
185 std::error_code EC;
186 fs::directory_iterator Iter(SearchDir, EC, false);
187 fs::directory_iterator End;
188 for (; Iter != End && !EC; Iter.increment(EC)) {
189 auto &Entry = *Iter;
190
191 auto Name = path::filename(Entry.path());
192
193 // Omit ".", ".."
194 if (Name == "." || Name == ".." || !Name.startswith(PartialItem))
195 continue;
196
197 // We have a match.
198
199 fs::file_status st;
Zachary Turner1f875342017-03-13 02:44:39 +0000200 if ((EC = Entry.status(st)))
Zachary Turner2cc5a182017-03-13 00:41:01 +0000201 continue;
202
203 // If it's a symlink, then we treat it as a directory as long as the target
204 // is a directory.
205 bool is_dir = fs::is_directory(st);
206 if (fs::is_symlink_file(st)) {
207 fs::file_status target_st;
208 if (!fs::status(Entry.path(), target_st))
209 is_dir = fs::is_directory(target_st);
210 }
211 if (only_directories && !is_dir)
212 continue;
213
214 // Shrink it back down so that it just has the original prefix the user
215 // typed and remove the part of the name which is common to the located
216 // item and what the user typed.
217 CompletionBuffer.resize(FullPrefixLen);
218 Name = Name.drop_front(PartialItem.size());
219 CompletionBuffer.append(Name);
220
221 if (is_dir) {
222 saw_directory = true;
223 path::append(CompletionBuffer, path::get_separator());
224 }
225
226 matches.AppendString(CompletionBuffer);
227 }
Zachary Turner0734e6a2017-03-12 20:01:37 +0000228
Kate Stoneb9c1b512016-09-06 20:57:50 +0000229 return matches.GetSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000230}
231
Kate Stoneb9c1b512016-09-06 20:57:50 +0000232int CommandCompletions::DiskFiles(CommandInterpreter &interpreter,
Zachary Turner4aa87532016-11-17 01:37:42 +0000233 llvm::StringRef partial_file_name,
Greg Claytonf21fead2013-05-14 23:43:18 +0000234 int match_start_point,
235 int max_return_elements,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000236 SearchFilter *searcher, bool &word_complete,
237 StringList &matches) {
Zachary Turner2cc5a182017-03-13 00:41:01 +0000238 word_complete = false;
239 StandardTildeExpressionResolver Resolver;
240 return DiskFiles(partial_file_name, matches, Resolver);
241}
242
243int CommandCompletions::DiskFiles(const llvm::Twine &partial_file_name,
244 StringList &matches,
245 TildeExpressionResolver &Resolver) {
246 bool word_complete;
247 int ret_val = DiskFilesOrDirectories(partial_file_name, false, word_complete,
248 matches, Resolver);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000249 return ret_val;
250}
251
252int CommandCompletions::DiskDirectories(
Zachary Turner4aa87532016-11-17 01:37:42 +0000253 CommandInterpreter &interpreter, llvm::StringRef partial_file_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000254 int match_start_point, int max_return_elements, SearchFilter *searcher,
255 bool &word_complete, StringList &matches) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000256 word_complete = false;
Zachary Turner2cc5a182017-03-13 00:41:01 +0000257 StandardTildeExpressionResolver Resolver;
258 return DiskDirectories(partial_file_name, matches, Resolver);
259}
260
261int CommandCompletions::DiskDirectories(const llvm::Twine &partial_file_name,
262 StringList &matches,
263 TildeExpressionResolver &Resolver) {
264 bool word_complete;
265 int ret_val = DiskFilesOrDirectories(partial_file_name, true, word_complete,
266 matches, Resolver);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000267 return ret_val;
268}
269
270int CommandCompletions::Modules(CommandInterpreter &interpreter,
Zachary Turner4aa87532016-11-17 01:37:42 +0000271 llvm::StringRef partial_file_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000272 int match_start_point, int max_return_elements,
273 SearchFilter *searcher, bool &word_complete,
274 StringList &matches) {
275 word_complete = true;
276 ModuleCompleter completer(interpreter, partial_file_name, match_start_point,
277 max_return_elements, matches);
278
279 if (searcher == nullptr) {
280 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
281 SearchFilterForUnconstrainedSearches null_searcher(target_sp);
282 completer.DoCompletion(&null_searcher);
283 } else {
284 completer.DoCompletion(searcher);
285 }
286 return matches.GetSize();
287}
288
289int CommandCompletions::Symbols(CommandInterpreter &interpreter,
Zachary Turner4aa87532016-11-17 01:37:42 +0000290 llvm::StringRef partial_file_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000291 int match_start_point, int max_return_elements,
292 SearchFilter *searcher, bool &word_complete,
293 StringList &matches) {
294 word_complete = true;
295 SymbolCompleter completer(interpreter, partial_file_name, match_start_point,
296 max_return_elements, matches);
297
298 if (searcher == nullptr) {
299 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
300 SearchFilterForUnconstrainedSearches null_searcher(target_sp);
301 completer.DoCompletion(&null_searcher);
302 } else {
303 completer.DoCompletion(searcher);
304 }
305 return matches.GetSize();
306}
307
308int CommandCompletions::SettingsNames(
Zachary Turner4aa87532016-11-17 01:37:42 +0000309 CommandInterpreter &interpreter, llvm::StringRef partial_setting_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000310 int match_start_point, int max_return_elements, SearchFilter *searcher,
311 bool &word_complete, StringList &matches) {
312 // Cache the full setting name list
313 static StringList g_property_names;
314 if (g_property_names.GetSize() == 0) {
315 // Generate the full setting name list on demand
316 lldb::OptionValuePropertiesSP properties_sp(
317 interpreter.GetDebugger().GetValueProperties());
318 if (properties_sp) {
319 StreamString strm;
320 properties_sp->DumpValue(nullptr, strm, OptionValue::eDumpOptionName);
321 const std::string &str = strm.GetString();
322 g_property_names.SplitIntoLines(str.c_str(), str.size());
323 }
324 }
325
326 size_t exact_matches_idx = SIZE_MAX;
327 const size_t num_matches = g_property_names.AutoComplete(
328 partial_setting_name, matches, exact_matches_idx);
329 word_complete = exact_matches_idx != SIZE_MAX;
330 return num_matches;
331}
332
333int CommandCompletions::PlatformPluginNames(
Zachary Turner4aa87532016-11-17 01:37:42 +0000334 CommandInterpreter &interpreter, llvm::StringRef partial_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000335 int match_start_point, int max_return_elements, SearchFilter *searcher,
336 bool &word_complete, lldb_private::StringList &matches) {
337 const uint32_t num_matches =
338 PluginManager::AutoCompletePlatformName(partial_name, matches);
339 word_complete = num_matches == 1;
340 return num_matches;
341}
342
343int CommandCompletions::ArchitectureNames(
Zachary Turner4aa87532016-11-17 01:37:42 +0000344 CommandInterpreter &interpreter, llvm::StringRef partial_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000345 int match_start_point, int max_return_elements, SearchFilter *searcher,
346 bool &word_complete, lldb_private::StringList &matches) {
347 const uint32_t num_matches = ArchSpec::AutoComplete(partial_name, matches);
348 word_complete = num_matches == 1;
349 return num_matches;
350}
351
352int CommandCompletions::VariablePath(
Zachary Turner4aa87532016-11-17 01:37:42 +0000353 CommandInterpreter &interpreter, llvm::StringRef partial_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000354 int match_start_point, int max_return_elements, SearchFilter *searcher,
355 bool &word_complete, lldb_private::StringList &matches) {
356 return Variable::AutoComplete(interpreter.GetExecutionContext(), partial_name,
357 matches, word_complete);
Greg Claytonf21fead2013-05-14 23:43:18 +0000358}
359
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000360CommandCompletions::Completer::Completer(CommandInterpreter &interpreter,
Zachary Turner4aa87532016-11-17 01:37:42 +0000361 llvm::StringRef completion_str,
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000362 int match_start_point,
363 int max_return_elements,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000364 StringList &matches)
365 : m_interpreter(interpreter), m_completion_str(completion_str),
366 m_match_start_point(match_start_point),
367 m_max_return_elements(max_return_elements), m_matches(matches) {}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000368
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000369CommandCompletions::Completer::~Completer() = default;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000370
371//----------------------------------------------------------------------
372// SourceFileCompleter
373//----------------------------------------------------------------------
374
Kate Stoneb9c1b512016-09-06 20:57:50 +0000375CommandCompletions::SourceFileCompleter::SourceFileCompleter(
376 CommandInterpreter &interpreter, bool include_support_files,
Zachary Turner4aa87532016-11-17 01:37:42 +0000377 llvm::StringRef completion_str, int match_start_point,
378 int max_return_elements, StringList &matches)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000379 : CommandCompletions::Completer(interpreter, completion_str,
380 match_start_point, max_return_elements,
381 matches),
382 m_include_support_files(include_support_files), m_matching_files() {
Malcolm Parsons771ef6d2016-11-02 20:34:10 +0000383 FileSpec partial_spec(m_completion_str, false);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000384 m_file_name = partial_spec.GetFilename().GetCString();
385 m_dir_name = partial_spec.GetDirectory().GetCString();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000386}
387
Kate Stoneb9c1b512016-09-06 20:57:50 +0000388Searcher::Depth CommandCompletions::SourceFileCompleter::GetDepth() {
389 return eDepthCompUnit;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000390}
391
392Searcher::CallbackReturn
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000393CommandCompletions::SourceFileCompleter::SearchCallback(SearchFilter &filter,
394 SymbolContext &context,
395 Address *addr,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000396 bool complete) {
397 if (context.comp_unit != nullptr) {
398 if (m_include_support_files) {
399 FileSpecList supporting_files = context.comp_unit->GetSupportFiles();
400 for (size_t sfiles = 0; sfiles < supporting_files.GetSize(); sfiles++) {
401 const FileSpec &sfile_spec =
402 supporting_files.GetFileSpecAtIndex(sfiles);
403 const char *sfile_file_name = sfile_spec.GetFilename().GetCString();
404 const char *sfile_dir_name = sfile_spec.GetFilename().GetCString();
405 bool match = false;
406 if (m_file_name && sfile_file_name &&
407 strstr(sfile_file_name, m_file_name) == sfile_file_name)
408 match = true;
409 if (match && m_dir_name && sfile_dir_name &&
410 strstr(sfile_dir_name, m_dir_name) != sfile_dir_name)
411 match = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000412
Kate Stoneb9c1b512016-09-06 20:57:50 +0000413 if (match) {
414 m_matching_files.AppendIfUnique(sfile_spec);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000415 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000416 }
417 } else {
418 const char *cur_file_name = context.comp_unit->GetFilename().GetCString();
419 const char *cur_dir_name = context.comp_unit->GetDirectory().GetCString();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000420
Kate Stoneb9c1b512016-09-06 20:57:50 +0000421 bool match = false;
422 if (m_file_name && cur_file_name &&
423 strstr(cur_file_name, m_file_name) == cur_file_name)
424 match = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000425
Kate Stoneb9c1b512016-09-06 20:57:50 +0000426 if (match && m_dir_name && cur_dir_name &&
427 strstr(cur_dir_name, m_dir_name) != cur_dir_name)
428 match = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000429
Kate Stoneb9c1b512016-09-06 20:57:50 +0000430 if (match) {
431 m_matching_files.AppendIfUnique(context.comp_unit);
432 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000433 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000434 }
435 return Searcher::eCallbackReturnContinue;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000436}
437
438size_t
Kate Stoneb9c1b512016-09-06 20:57:50 +0000439CommandCompletions::SourceFileCompleter::DoCompletion(SearchFilter *filter) {
440 filter->Search(*this);
441 // Now convert the filelist to completions:
442 for (size_t i = 0; i < m_matching_files.GetSize(); i++) {
443 m_matches.AppendString(
444 m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString());
445 }
446 return m_matches.GetSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000447}
448
449//----------------------------------------------------------------------
450// SymbolCompleter
451//----------------------------------------------------------------------
452
Kate Stoneb9c1b512016-09-06 20:57:50 +0000453static bool regex_chars(const char comp) {
454 return (comp == '[' || comp == ']' || comp == '(' || comp == ')' ||
455 comp == '{' || comp == '}' || comp == '+' || comp == '.' ||
456 comp == '*' || comp == '|' || comp == '^' || comp == '$' ||
457 comp == '\\' || comp == '?');
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000458}
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000459
Kate Stoneb9c1b512016-09-06 20:57:50 +0000460CommandCompletions::SymbolCompleter::SymbolCompleter(
Zachary Turner4aa87532016-11-17 01:37:42 +0000461 CommandInterpreter &interpreter, llvm::StringRef completion_str,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000462 int match_start_point, int max_return_elements, StringList &matches)
463 : CommandCompletions::Completer(interpreter, completion_str,
464 match_start_point, max_return_elements,
465 matches) {
466 std::string regex_str;
Zachary Turner4aa87532016-11-17 01:37:42 +0000467 if (!completion_str.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000468 regex_str.append("^");
469 regex_str.append(completion_str);
470 } else {
471 // Match anything since the completion string is empty
472 regex_str.append(".");
473 }
474 std::string::iterator pos =
475 find_if(regex_str.begin() + 1, regex_str.end(), regex_chars);
476 while (pos < regex_str.end()) {
477 pos = regex_str.insert(pos, '\\');
478 pos = find_if(pos + 2, regex_str.end(), regex_chars);
479 }
Zachary Turner95eae422016-09-21 16:01:28 +0000480 m_regex.Compile(regex_str);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000481}
482
Kate Stoneb9c1b512016-09-06 20:57:50 +0000483Searcher::Depth CommandCompletions::SymbolCompleter::GetDepth() {
484 return eDepthModule;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000485}
486
Kate Stoneb9c1b512016-09-06 20:57:50 +0000487Searcher::CallbackReturn CommandCompletions::SymbolCompleter::SearchCallback(
488 SearchFilter &filter, SymbolContext &context, Address *addr,
489 bool complete) {
490 if (context.module_sp) {
491 SymbolContextList sc_list;
492 const bool include_symbols = true;
493 const bool include_inlines = true;
494 const bool append = true;
495 context.module_sp->FindFunctions(m_regex, include_symbols, include_inlines,
496 append, sc_list);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000497
Kate Stoneb9c1b512016-09-06 20:57:50 +0000498 SymbolContext sc;
499 // Now add the functions & symbols to the list - only add if unique:
500 for (uint32_t i = 0; i < sc_list.GetSize(); i++) {
501 if (sc_list.GetContextAtIndex(i, sc)) {
502 ConstString func_name = sc.GetFunctionName(Mangled::ePreferDemangled);
503 if (!func_name.IsEmpty())
504 m_match_set.insert(func_name);
505 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000506 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000507 }
508 return Searcher::eCallbackReturnContinue;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000509}
510
Kate Stoneb9c1b512016-09-06 20:57:50 +0000511size_t CommandCompletions::SymbolCompleter::DoCompletion(SearchFilter *filter) {
512 filter->Search(*this);
513 collection::iterator pos = m_match_set.begin(), end = m_match_set.end();
514 for (pos = m_match_set.begin(); pos != end; pos++)
515 m_matches.AppendString((*pos).GetCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000516
Kate Stoneb9c1b512016-09-06 20:57:50 +0000517 return m_matches.GetSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000518}
519
520//----------------------------------------------------------------------
521// ModuleCompleter
522//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000523CommandCompletions::ModuleCompleter::ModuleCompleter(
Zachary Turner4aa87532016-11-17 01:37:42 +0000524 CommandInterpreter &interpreter, llvm::StringRef completion_str,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000525 int match_start_point, int max_return_elements, StringList &matches)
526 : CommandCompletions::Completer(interpreter, completion_str,
527 match_start_point, max_return_elements,
528 matches) {
Malcolm Parsons771ef6d2016-11-02 20:34:10 +0000529 FileSpec partial_spec(m_completion_str, false);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000530 m_file_name = partial_spec.GetFilename().GetCString();
531 m_dir_name = partial_spec.GetDirectory().GetCString();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000532}
533
Kate Stoneb9c1b512016-09-06 20:57:50 +0000534Searcher::Depth CommandCompletions::ModuleCompleter::GetDepth() {
535 return eDepthModule;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000536}
537
Kate Stoneb9c1b512016-09-06 20:57:50 +0000538Searcher::CallbackReturn CommandCompletions::ModuleCompleter::SearchCallback(
539 SearchFilter &filter, SymbolContext &context, Address *addr,
540 bool complete) {
541 if (context.module_sp) {
542 const char *cur_file_name =
543 context.module_sp->GetFileSpec().GetFilename().GetCString();
544 const char *cur_dir_name =
545 context.module_sp->GetFileSpec().GetDirectory().GetCString();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000546
Kate Stoneb9c1b512016-09-06 20:57:50 +0000547 bool match = false;
548 if (m_file_name && cur_file_name &&
549 strstr(cur_file_name, m_file_name) == cur_file_name)
550 match = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000551
Kate Stoneb9c1b512016-09-06 20:57:50 +0000552 if (match && m_dir_name && cur_dir_name &&
553 strstr(cur_dir_name, m_dir_name) != cur_dir_name)
554 match = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000555
Kate Stoneb9c1b512016-09-06 20:57:50 +0000556 if (match) {
557 m_matches.AppendString(cur_file_name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000558 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000559 }
560 return Searcher::eCallbackReturnContinue;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000561}
562
Kate Stoneb9c1b512016-09-06 20:57:50 +0000563size_t CommandCompletions::ModuleCompleter::DoCompletion(SearchFilter *filter) {
564 filter->Search(*this);
565 return m_matches.GetSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000566}