blob: fc3e8d0662d25c20981593c2a8eb37f0abafabce [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/CommandCompletions.h"
27#include "lldb/Interpreter/CommandInterpreter.h"
Zachary Turner633a29c2015-03-04 01:58:01 +000028#include "lldb/Interpreter/OptionValueProperties.h"
Greg Clayton1f746072012-08-29 21:13:06 +000029#include "lldb/Symbol/CompileUnit.h"
Greg Claytonf21fead2013-05-14 23:43:18 +000030#include "lldb/Symbol/Variable.h"
Greg Clayton9b62fd22011-02-01 05:15:22 +000031#include "lldb/Target/Target.h"
Pavel Labath145d95c2018-04-17 18:53:35 +000032#include "lldb/Utility/Args.h"
Zachary Turner5713a052017-03-22 18:40:07 +000033#include "lldb/Utility/FileSpec.h"
Zachary Turner2f3df612017-04-06 21:28:29 +000034#include "lldb/Utility/StreamString.h"
Zachary Turner2cc5a182017-03-13 00:41:01 +000035#include "lldb/Utility/TildeExpressionResolver.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000036
Zachary Turner190fadc2016-03-22 17:58:09 +000037#include "llvm/ADT/SmallString.h"
Zachary Turner7d86ee52017-03-08 17:56:08 +000038#include "llvm/Support/FileSystem.h"
Zachary Turner2cc5a182017-03-13 00:41:01 +000039#include "llvm/Support/Path.h"
Zachary Turner190fadc2016-03-22 17:58:09 +000040
Chris Lattner30fdc8d2010-06-08 16:52:24 +000041using namespace lldb_private;
42
43CommandCompletions::CommonCompletionElement
Kate Stoneb9c1b512016-09-06 20:57:50 +000044 CommandCompletions::g_common_completions[] = {
45 {eCustomCompletion, nullptr},
46 {eSourceFileCompletion, CommandCompletions::SourceFiles},
47 {eDiskFileCompletion, CommandCompletions::DiskFiles},
48 {eDiskDirectoryCompletion, CommandCompletions::DiskDirectories},
49 {eSymbolCompletion, CommandCompletions::Symbols},
50 {eModuleCompletion, CommandCompletions::Modules},
51 {eSettingsNameCompletion, CommandCompletions::SettingsNames},
52 {ePlatformPluginCompletion, CommandCompletions::PlatformPluginNames},
53 {eArchitectureCompletion, CommandCompletions::ArchitectureNames},
54 {eVariablePathCompletion, CommandCompletions::VariablePath},
55 {eNoCompletion, nullptr} // This one has to be last in the list.
Chris Lattner30fdc8d2010-06-08 16:52:24 +000056};
57
Kate Stoneb9c1b512016-09-06 20:57:50 +000058bool CommandCompletions::InvokeCommonCompletionCallbacks(
59 CommandInterpreter &interpreter, uint32_t completion_mask,
Raphael Isemanna2e76c02018-07-13 18:28:14 +000060 CompletionRequest &request, SearchFilter *searcher) {
Kate Stoneb9c1b512016-09-06 20:57:50 +000061 bool handled = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000062
Kate Stoneb9c1b512016-09-06 20:57:50 +000063 if (completion_mask & eCustomCompletion)
64 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000065
Kate Stoneb9c1b512016-09-06 20:57:50 +000066 for (int i = 0;; i++) {
67 if (g_common_completions[i].type == eNoCompletion)
68 break;
69 else if ((g_common_completions[i].type & completion_mask) ==
70 g_common_completions[i].type &&
71 g_common_completions[i].callback != nullptr) {
72 handled = true;
Raphael Isemanna2e76c02018-07-13 18:28:14 +000073 g_common_completions[i].callback(interpreter, request, searcher);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000074 }
Kate Stoneb9c1b512016-09-06 20:57:50 +000075 }
76 return handled;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000077}
78
Kate Stoneb9c1b512016-09-06 20:57:50 +000079int CommandCompletions::SourceFiles(CommandInterpreter &interpreter,
Raphael Isemanna2e76c02018-07-13 18:28:14 +000080 CompletionRequest &request,
81 SearchFilter *searcher) {
82 request.SetWordComplete(true);
Kate Stoneb9c1b512016-09-06 20:57:50 +000083 // Find some way to switch "include support files..."
Raphael Isemanna2e76c02018-07-13 18:28:14 +000084 SourceFileCompleter completer(interpreter, false, request);
Kate Stoneb9c1b512016-09-06 20:57:50 +000085
86 if (searcher == nullptr) {
87 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
88 SearchFilterForUnconstrainedSearches null_searcher(target_sp);
89 completer.DoCompletion(&null_searcher);
90 } else {
91 completer.DoCompletion(searcher);
92 }
Raphael Isemann1a6d7ab2018-07-27 18:42:46 +000093 return request.GetNumberOfMatches();
Jim Ingham558ce122010-06-30 05:02:46 +000094}
95
Zachary Turner2cc5a182017-03-13 00:41:01 +000096static int DiskFilesOrDirectories(const llvm::Twine &partial_name,
Raphael Isemanna2e76c02018-07-13 18:28:14 +000097 bool only_directories, StringList &matches,
Zachary Turner2cc5a182017-03-13 00:41:01 +000098 TildeExpressionResolver &Resolver) {
99 matches.Clear();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000100
Zachary Turner2cc5a182017-03-13 00:41:01 +0000101 llvm::SmallString<256> CompletionBuffer;
102 llvm::SmallString<256> Storage;
103 partial_name.toVector(CompletionBuffer);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000104
Zachary Turner2cc5a182017-03-13 00:41:01 +0000105 if (CompletionBuffer.size() >= PATH_MAX)
Raphael Isemann1a6d7ab2018-07-27 18:42:46 +0000106 return matches.GetSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000107
Zachary Turner2cc5a182017-03-13 00:41:01 +0000108 namespace fs = llvm::sys::fs;
109 namespace path = llvm::sys::path;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000110
Zachary Turner2cc5a182017-03-13 00:41:01 +0000111 llvm::StringRef SearchDir;
112 llvm::StringRef PartialItem;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000113
Zachary Turner2cc5a182017-03-13 00:41:01 +0000114 if (CompletionBuffer.startswith("~")) {
115 llvm::StringRef Buffer(CompletionBuffer);
Zachary Turner5c5091f2017-03-16 22:28:04 +0000116 size_t FirstSep =
117 Buffer.find_if([](char c) { return path::is_separator(c); });
Kate Stoneb9c1b512016-09-06 20:57:50 +0000118
Zachary Turner2cc5a182017-03-13 00:41:01 +0000119 llvm::StringRef Username = Buffer.take_front(FirstSep);
120 llvm::StringRef Remainder;
121 if (FirstSep != llvm::StringRef::npos)
122 Remainder = Buffer.drop_front(FirstSep + 1);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000123
Zachary Turner2cc5a182017-03-13 00:41:01 +0000124 llvm::SmallString<PATH_MAX> Resolved;
125 if (!Resolver.ResolveExact(Username, Resolved)) {
126 // We couldn't resolve it as a full username. If there were no slashes
127 // then this might be a partial username. We try to resolve it as such
128 // but after that, we're done regardless of any matches.
129 if (FirstSep == llvm::StringRef::npos) {
130 llvm::StringSet<> MatchSet;
Raphael Isemanna2e76c02018-07-13 18:28:14 +0000131 Resolver.ResolvePartial(Username, MatchSet);
Zachary Turner2cc5a182017-03-13 00:41:01 +0000132 for (const auto &S : MatchSet) {
133 Resolved = S.getKey();
134 path::append(Resolved, path::get_separator());
135 matches.AppendString(Resolved);
136 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000137 }
Zachary Turner0734e6a2017-03-12 20:01:37 +0000138 return matches.GetSize();
Zachary Turner2cc5a182017-03-13 00:41:01 +0000139 }
140
Adrian Prantl05097242018-04-30 16:49:04 +0000141 // If there was no trailing slash, then we're done as soon as we resolve
142 // the expression to the correct directory. Otherwise we need to continue
Zachary Turner2cc5a182017-03-13 00:41:01 +0000143 // looking for matches within that directory.
144 if (FirstSep == llvm::StringRef::npos) {
145 // Make sure it ends with a separator.
146 path::append(CompletionBuffer, path::get_separator());
Zachary Turner2cc5a182017-03-13 00:41:01 +0000147 matches.AppendString(CompletionBuffer);
Raphael Isemann1a6d7ab2018-07-27 18:42:46 +0000148 return matches.GetSize();
Zachary Turner2cc5a182017-03-13 00:41:01 +0000149 }
150
151 // We want to keep the form the user typed, so we special case this to
152 // search in the fully resolved directory, but CompletionBuffer keeps the
153 // unmodified form that the user typed.
154 Storage = Resolved;
Pavel Labath88ec2e42018-06-29 10:27:18 +0000155 llvm::StringRef RemainderDir = path::parent_path(Remainder);
Raphael Isemann4621e0b2018-06-18 20:11:38 +0000156 if (!RemainderDir.empty()) {
157 // Append the remaining path to the resolved directory.
158 Storage.append(path::get_separator());
159 Storage.append(RemainderDir);
160 }
Raphael Isemann17843882018-01-22 09:17:16 +0000161 SearchDir = Storage;
Zachary Turner2cc5a182017-03-13 00:41:01 +0000162 } else {
163 SearchDir = path::parent_path(CompletionBuffer);
Zachary Turnerd5bd3a12017-03-12 18:18:50 +0000164 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000165
Zachary Turner2cc5a182017-03-13 00:41:01 +0000166 size_t FullPrefixLen = CompletionBuffer.size();
Zachary Turner0734e6a2017-03-12 20:01:37 +0000167
Zachary Turner2cc5a182017-03-13 00:41:01 +0000168 PartialItem = path::filename(CompletionBuffer);
Frederic Riss78a10a72018-08-31 23:03:28 +0000169
170 // path::filename() will return "." when the passed path ends with a
171 // directory separator. We have to filter those out, but only when the
172 // "." doesn't come from the completion request itself.
173 if (PartialItem == "." && path::is_separator(CompletionBuffer.back()))
Zachary Turner2cc5a182017-03-13 00:41:01 +0000174 PartialItem = llvm::StringRef();
Zachary Turner0734e6a2017-03-12 20:01:37 +0000175
Zachary Turner426d1372017-04-15 02:44:53 +0000176 if (SearchDir.empty()) {
177 llvm::sys::fs::current_path(Storage);
178 SearchDir = Storage;
179 }
Zachary Turner2cc5a182017-03-13 00:41:01 +0000180 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
Peter Collingbourne0dfdb442017-10-10 22:19:46 +0000199 llvm::ErrorOr<fs::basic_file_status> st = Entry.status();
200 if (!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.
Peter Collingbourne0dfdb442017-10-10 22:19:46 +0000205 bool is_dir = fs::is_directory(*st);
206 if (fs::is_symlink_file(*st)) {
Zachary Turner2cc5a182017-03-13 00:41:01 +0000207 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) {
Zachary Turner2cc5a182017-03-13 00:41:01 +0000222 path::append(CompletionBuffer, path::get_separator());
223 }
224
225 matches.AppendString(CompletionBuffer);
226 }
Zachary Turner0734e6a2017-03-12 20:01:37 +0000227
Kate Stoneb9c1b512016-09-06 20:57:50 +0000228 return matches.GetSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000229}
230
Raphael Isemann1a6d7ab2018-07-27 18:42:46 +0000231static int DiskFilesOrDirectories(CompletionRequest &request,
232 bool only_directories) {
233 request.SetWordComplete(false);
234 StandardTildeExpressionResolver resolver;
235 StringList matches;
236 DiskFilesOrDirectories(request.GetCursorArgumentPrefix(), only_directories,
237 matches, resolver);
238 request.AddCompletions(matches);
239 return request.GetNumberOfMatches();
240}
241
Kate Stoneb9c1b512016-09-06 20:57:50 +0000242int CommandCompletions::DiskFiles(CommandInterpreter &interpreter,
Raphael Isemanna2e76c02018-07-13 18:28:14 +0000243 CompletionRequest &request,
244 SearchFilter *searcher) {
Raphael Isemann1a6d7ab2018-07-27 18:42:46 +0000245 return DiskFilesOrDirectories(request, /*only_dirs*/ false);
Zachary Turner2cc5a182017-03-13 00:41:01 +0000246}
247
248int CommandCompletions::DiskFiles(const llvm::Twine &partial_file_name,
249 StringList &matches,
250 TildeExpressionResolver &Resolver) {
Raphael Isemanna2e76c02018-07-13 18:28:14 +0000251 return DiskFilesOrDirectories(partial_file_name, false, matches, Resolver);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000252}
253
Raphael Isemanna2e76c02018-07-13 18:28:14 +0000254int CommandCompletions::DiskDirectories(CommandInterpreter &interpreter,
255 CompletionRequest &request,
256 SearchFilter *searcher) {
Raphael Isemann1a6d7ab2018-07-27 18:42:46 +0000257 return DiskFilesOrDirectories(request, /*only_dirs*/ true);
Zachary Turner2cc5a182017-03-13 00:41:01 +0000258}
259
260int CommandCompletions::DiskDirectories(const llvm::Twine &partial_file_name,
261 StringList &matches,
262 TildeExpressionResolver &Resolver) {
Raphael Isemanna2e76c02018-07-13 18:28:14 +0000263 return DiskFilesOrDirectories(partial_file_name, true, matches, Resolver);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000264}
265
266int CommandCompletions::Modules(CommandInterpreter &interpreter,
Raphael Isemanna2e76c02018-07-13 18:28:14 +0000267 CompletionRequest &request,
268 SearchFilter *searcher) {
269 request.SetWordComplete(true);
270 ModuleCompleter completer(interpreter, request);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000271
272 if (searcher == nullptr) {
273 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
274 SearchFilterForUnconstrainedSearches null_searcher(target_sp);
275 completer.DoCompletion(&null_searcher);
276 } else {
277 completer.DoCompletion(searcher);
278 }
Raphael Isemann1a6d7ab2018-07-27 18:42:46 +0000279 return request.GetNumberOfMatches();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000280}
281
282int CommandCompletions::Symbols(CommandInterpreter &interpreter,
Raphael Isemanna2e76c02018-07-13 18:28:14 +0000283 CompletionRequest &request,
284 SearchFilter *searcher) {
285 request.SetWordComplete(true);
286 SymbolCompleter completer(interpreter, request);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000287
288 if (searcher == nullptr) {
289 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
290 SearchFilterForUnconstrainedSearches null_searcher(target_sp);
291 completer.DoCompletion(&null_searcher);
292 } else {
293 completer.DoCompletion(searcher);
294 }
Raphael Isemann1a6d7ab2018-07-27 18:42:46 +0000295 return request.GetNumberOfMatches();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000296}
297
Raphael Isemanna2e76c02018-07-13 18:28:14 +0000298int CommandCompletions::SettingsNames(CommandInterpreter &interpreter,
299 CompletionRequest &request,
300 SearchFilter *searcher) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000301 // Cache the full setting name list
302 static StringList g_property_names;
303 if (g_property_names.GetSize() == 0) {
304 // Generate the full setting name list on demand
305 lldb::OptionValuePropertiesSP properties_sp(
306 interpreter.GetDebugger().GetValueProperties());
307 if (properties_sp) {
308 StreamString strm;
309 properties_sp->DumpValue(nullptr, strm, OptionValue::eDumpOptionName);
310 const std::string &str = strm.GetString();
311 g_property_names.SplitIntoLines(str.c_str(), str.size());
312 }
313 }
314
315 size_t exact_matches_idx = SIZE_MAX;
Raphael Isemann1a6d7ab2018-07-27 18:42:46 +0000316 StringList matches;
317 g_property_names.AutoComplete(request.GetCursorArgumentPrefix(), matches,
318 exact_matches_idx);
Raphael Isemanna2e76c02018-07-13 18:28:14 +0000319 request.SetWordComplete(exact_matches_idx != SIZE_MAX);
Raphael Isemann1a6d7ab2018-07-27 18:42:46 +0000320 request.AddCompletions(matches);
321 return request.GetNumberOfMatches();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000322}
323
Raphael Isemanna2e76c02018-07-13 18:28:14 +0000324int CommandCompletions::PlatformPluginNames(CommandInterpreter &interpreter,
325 CompletionRequest &request,
326 SearchFilter *searcher) {
Raphael Isemann1a6d7ab2018-07-27 18:42:46 +0000327 StringList new_matches;
328 std::size_t num_matches = PluginManager::AutoCompletePlatformName(
329 request.GetCursorArgumentPrefix(), new_matches);
Raphael Isemanna2e76c02018-07-13 18:28:14 +0000330 request.SetWordComplete(num_matches == 1);
Raphael Isemann1a6d7ab2018-07-27 18:42:46 +0000331 request.AddCompletions(new_matches);
332 return request.GetNumberOfMatches();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000333}
334
Raphael Isemanna2e76c02018-07-13 18:28:14 +0000335int CommandCompletions::ArchitectureNames(CommandInterpreter &interpreter,
336 CompletionRequest &request,
337 SearchFilter *searcher) {
338 const uint32_t num_matches = ArchSpec::AutoComplete(request);
339 request.SetWordComplete(num_matches == 1);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000340 return num_matches;
341}
342
Raphael Isemanna2e76c02018-07-13 18:28:14 +0000343int CommandCompletions::VariablePath(CommandInterpreter &interpreter,
344 CompletionRequest &request,
345 SearchFilter *searcher) {
346 return Variable::AutoComplete(interpreter.GetExecutionContext(), request);
Greg Claytonf21fead2013-05-14 23:43:18 +0000347}
348
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000349CommandCompletions::Completer::Completer(CommandInterpreter &interpreter,
Raphael Isemanna2e76c02018-07-13 18:28:14 +0000350 CompletionRequest &request)
351 : m_interpreter(interpreter), m_request(request) {}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000352
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000353CommandCompletions::Completer::~Completer() = default;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000354
355//----------------------------------------------------------------------
356// SourceFileCompleter
357//----------------------------------------------------------------------
358
Kate Stoneb9c1b512016-09-06 20:57:50 +0000359CommandCompletions::SourceFileCompleter::SourceFileCompleter(
360 CommandInterpreter &interpreter, bool include_support_files,
Raphael Isemanna2e76c02018-07-13 18:28:14 +0000361 CompletionRequest &request)
362 : CommandCompletions::Completer(interpreter, request),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000363 m_include_support_files(include_support_files), m_matching_files() {
Raphael Isemanna2e76c02018-07-13 18:28:14 +0000364 FileSpec partial_spec(m_request.GetCursorArgumentPrefix(), false);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000365 m_file_name = partial_spec.GetFilename().GetCString();
366 m_dir_name = partial_spec.GetDirectory().GetCString();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000367}
368
Kate Stoneb9c1b512016-09-06 20:57:50 +0000369Searcher::Depth CommandCompletions::SourceFileCompleter::GetDepth() {
370 return eDepthCompUnit;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000371}
372
373Searcher::CallbackReturn
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000374CommandCompletions::SourceFileCompleter::SearchCallback(SearchFilter &filter,
375 SymbolContext &context,
376 Address *addr,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000377 bool complete) {
378 if (context.comp_unit != nullptr) {
379 if (m_include_support_files) {
380 FileSpecList supporting_files = context.comp_unit->GetSupportFiles();
381 for (size_t sfiles = 0; sfiles < supporting_files.GetSize(); sfiles++) {
382 const FileSpec &sfile_spec =
383 supporting_files.GetFileSpecAtIndex(sfiles);
384 const char *sfile_file_name = sfile_spec.GetFilename().GetCString();
385 const char *sfile_dir_name = sfile_spec.GetFilename().GetCString();
386 bool match = false;
387 if (m_file_name && sfile_file_name &&
388 strstr(sfile_file_name, m_file_name) == sfile_file_name)
389 match = true;
390 if (match && m_dir_name && sfile_dir_name &&
391 strstr(sfile_dir_name, m_dir_name) != sfile_dir_name)
392 match = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000393
Kate Stoneb9c1b512016-09-06 20:57:50 +0000394 if (match) {
395 m_matching_files.AppendIfUnique(sfile_spec);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000396 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000397 }
398 } else {
399 const char *cur_file_name = context.comp_unit->GetFilename().GetCString();
400 const char *cur_dir_name = context.comp_unit->GetDirectory().GetCString();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000401
Kate Stoneb9c1b512016-09-06 20:57:50 +0000402 bool match = false;
403 if (m_file_name && cur_file_name &&
404 strstr(cur_file_name, m_file_name) == cur_file_name)
405 match = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000406
Kate Stoneb9c1b512016-09-06 20:57:50 +0000407 if (match && m_dir_name && cur_dir_name &&
408 strstr(cur_dir_name, m_dir_name) != cur_dir_name)
409 match = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000410
Kate Stoneb9c1b512016-09-06 20:57:50 +0000411 if (match) {
412 m_matching_files.AppendIfUnique(context.comp_unit);
413 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000414 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000415 }
416 return Searcher::eCallbackReturnContinue;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000417}
418
419size_t
Kate Stoneb9c1b512016-09-06 20:57:50 +0000420CommandCompletions::SourceFileCompleter::DoCompletion(SearchFilter *filter) {
421 filter->Search(*this);
422 // Now convert the filelist to completions:
423 for (size_t i = 0; i < m_matching_files.GetSize(); i++) {
Raphael Isemann1a6d7ab2018-07-27 18:42:46 +0000424 m_request.AddCompletion(
Kate Stoneb9c1b512016-09-06 20:57:50 +0000425 m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString());
426 }
Raphael Isemann1a6d7ab2018-07-27 18:42:46 +0000427 return m_request.GetNumberOfMatches();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000428}
429
430//----------------------------------------------------------------------
431// SymbolCompleter
432//----------------------------------------------------------------------
433
Kate Stoneb9c1b512016-09-06 20:57:50 +0000434static bool regex_chars(const char comp) {
435 return (comp == '[' || comp == ']' || comp == '(' || comp == ')' ||
436 comp == '{' || comp == '}' || comp == '+' || comp == '.' ||
437 comp == '*' || comp == '|' || comp == '^' || comp == '$' ||
438 comp == '\\' || comp == '?');
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000439}
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000440
Kate Stoneb9c1b512016-09-06 20:57:50 +0000441CommandCompletions::SymbolCompleter::SymbolCompleter(
Raphael Isemanna2e76c02018-07-13 18:28:14 +0000442 CommandInterpreter &interpreter, CompletionRequest &request)
443 : CommandCompletions::Completer(interpreter, request) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000444 std::string regex_str;
Raphael Isemanna2e76c02018-07-13 18:28:14 +0000445 if (!m_request.GetCursorArgumentPrefix().empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000446 regex_str.append("^");
Raphael Isemanna2e76c02018-07-13 18:28:14 +0000447 regex_str.append(m_request.GetCursorArgumentPrefix());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000448 } else {
449 // Match anything since the completion string is empty
450 regex_str.append(".");
451 }
452 std::string::iterator pos =
453 find_if(regex_str.begin() + 1, regex_str.end(), regex_chars);
454 while (pos < regex_str.end()) {
455 pos = regex_str.insert(pos, '\\');
456 pos = find_if(pos + 2, regex_str.end(), regex_chars);
457 }
Zachary Turner95eae422016-09-21 16:01:28 +0000458 m_regex.Compile(regex_str);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000459}
460
Kate Stoneb9c1b512016-09-06 20:57:50 +0000461Searcher::Depth CommandCompletions::SymbolCompleter::GetDepth() {
462 return eDepthModule;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000463}
464
Kate Stoneb9c1b512016-09-06 20:57:50 +0000465Searcher::CallbackReturn CommandCompletions::SymbolCompleter::SearchCallback(
466 SearchFilter &filter, SymbolContext &context, Address *addr,
467 bool complete) {
468 if (context.module_sp) {
469 SymbolContextList sc_list;
470 const bool include_symbols = true;
471 const bool include_inlines = true;
472 const bool append = true;
473 context.module_sp->FindFunctions(m_regex, include_symbols, include_inlines,
474 append, sc_list);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000475
Kate Stoneb9c1b512016-09-06 20:57:50 +0000476 SymbolContext sc;
477 // Now add the functions & symbols to the list - only add if unique:
478 for (uint32_t i = 0; i < sc_list.GetSize(); i++) {
479 if (sc_list.GetContextAtIndex(i, sc)) {
480 ConstString func_name = sc.GetFunctionName(Mangled::ePreferDemangled);
481 if (!func_name.IsEmpty())
482 m_match_set.insert(func_name);
483 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000484 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000485 }
486 return Searcher::eCallbackReturnContinue;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000487}
488
Kate Stoneb9c1b512016-09-06 20:57:50 +0000489size_t CommandCompletions::SymbolCompleter::DoCompletion(SearchFilter *filter) {
490 filter->Search(*this);
491 collection::iterator pos = m_match_set.begin(), end = m_match_set.end();
492 for (pos = m_match_set.begin(); pos != end; pos++)
Raphael Isemann1a6d7ab2018-07-27 18:42:46 +0000493 m_request.AddCompletion((*pos).GetCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000494
Raphael Isemann1a6d7ab2018-07-27 18:42:46 +0000495 return m_request.GetNumberOfMatches();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000496}
497
498//----------------------------------------------------------------------
499// ModuleCompleter
500//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000501CommandCompletions::ModuleCompleter::ModuleCompleter(
Raphael Isemanna2e76c02018-07-13 18:28:14 +0000502 CommandInterpreter &interpreter, CompletionRequest &request)
503 : CommandCompletions::Completer(interpreter, request) {
504 FileSpec partial_spec(m_request.GetCursorArgumentPrefix(), false);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000505 m_file_name = partial_spec.GetFilename().GetCString();
506 m_dir_name = partial_spec.GetDirectory().GetCString();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000507}
508
Kate Stoneb9c1b512016-09-06 20:57:50 +0000509Searcher::Depth CommandCompletions::ModuleCompleter::GetDepth() {
510 return eDepthModule;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000511}
512
Kate Stoneb9c1b512016-09-06 20:57:50 +0000513Searcher::CallbackReturn CommandCompletions::ModuleCompleter::SearchCallback(
514 SearchFilter &filter, SymbolContext &context, Address *addr,
515 bool complete) {
516 if (context.module_sp) {
517 const char *cur_file_name =
518 context.module_sp->GetFileSpec().GetFilename().GetCString();
519 const char *cur_dir_name =
520 context.module_sp->GetFileSpec().GetDirectory().GetCString();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000521
Kate Stoneb9c1b512016-09-06 20:57:50 +0000522 bool match = false;
523 if (m_file_name && cur_file_name &&
524 strstr(cur_file_name, m_file_name) == cur_file_name)
525 match = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000526
Kate Stoneb9c1b512016-09-06 20:57:50 +0000527 if (match && m_dir_name && cur_dir_name &&
528 strstr(cur_dir_name, m_dir_name) != cur_dir_name)
529 match = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000530
Kate Stoneb9c1b512016-09-06 20:57:50 +0000531 if (match) {
Raphael Isemann1a6d7ab2018-07-27 18:42:46 +0000532 m_request.AddCompletion(cur_file_name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000533 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000534 }
535 return Searcher::eCallbackReturnContinue;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000536}
537
Kate Stoneb9c1b512016-09-06 20:57:50 +0000538size_t CommandCompletions::ModuleCompleter::DoCompletion(SearchFilter *filter) {
539 filter->Search(*this);
Raphael Isemann1a6d7ab2018-07-27 18:42:46 +0000540 return m_request.GetNumberOfMatches();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000541}