mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-29 19:56:05 +00:00
415 lines
13 KiB
C++
415 lines
13 KiB
C++
//===-- CommandCompletions.cpp ----------------------------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
// C Includes
|
|
// C++ Includes
|
|
// Other libraries and framework includes
|
|
// Project includes
|
|
#include "lldb/Interpreter/Args.h"
|
|
#include "lldb/Interpreter/CommandInterpreter.h"
|
|
#include "lldb/Core/FileSpecList.h"
|
|
#include "lldb/Target/Target.h"
|
|
#include "lldb/Interpreter/CommandCompletions.h"
|
|
|
|
|
|
using namespace lldb_private;
|
|
|
|
CommandCompletions::CommonCompletionElement
|
|
CommandCompletions::g_common_completions[] =
|
|
{
|
|
{eCustomCompletion, NULL},
|
|
{eSourceFileCompletion, CommandCompletions::SourceFiles},
|
|
{eDiskFileCompletion, NULL},
|
|
{eSymbolCompletion, CommandCompletions::Symbols},
|
|
{eModuleCompletion, CommandCompletions::Modules},
|
|
{eNoCompletion, NULL} // This one has to be last in the list.
|
|
};
|
|
|
|
bool
|
|
CommandCompletions::InvokeCommonCompletionCallbacks (uint32_t completion_mask,
|
|
const char *completion_str,
|
|
int match_start_point,
|
|
int max_return_elements,
|
|
lldb_private::CommandInterpreter *interpreter,
|
|
SearchFilter *searcher,
|
|
lldb_private::StringList &matches)
|
|
{
|
|
bool handled = false;
|
|
|
|
if (completion_mask & eCustomCompletion)
|
|
return false;
|
|
|
|
for (int i = 0; ; i++)
|
|
{
|
|
if (g_common_completions[i].type == eNoCompletion)
|
|
break;
|
|
else if ((g_common_completions[i].type & completion_mask) == g_common_completions[i].type
|
|
&& g_common_completions[i].callback != NULL)
|
|
{
|
|
handled = true;
|
|
g_common_completions[i].callback (completion_str,
|
|
match_start_point,
|
|
max_return_elements,
|
|
interpreter,
|
|
searcher,
|
|
matches);
|
|
}
|
|
}
|
|
return handled;
|
|
}
|
|
|
|
int
|
|
CommandCompletions::SourceFiles (const char *partial_file_name,
|
|
int match_start_point,
|
|
int max_return_elements,
|
|
lldb_private::CommandInterpreter *interpreter,
|
|
SearchFilter *searcher,
|
|
lldb_private::StringList &matches)
|
|
{
|
|
// Find some way to switch "include support files..."
|
|
SourceFileCompleter completer (false, partial_file_name, match_start_point, max_return_elements, interpreter,
|
|
matches);
|
|
|
|
if (searcher == NULL)
|
|
{
|
|
lldb::TargetSP target_sp = interpreter->Context()->GetTarget()->GetSP();
|
|
SearchFilter null_searcher (target_sp);
|
|
completer.DoCompletion (&null_searcher);
|
|
}
|
|
else
|
|
{
|
|
completer.DoCompletion (searcher);
|
|
}
|
|
return matches.GetSize();
|
|
}
|
|
|
|
int
|
|
CommandCompletions::Modules (const char *partial_file_name,
|
|
int match_start_point,
|
|
int max_return_elements,
|
|
lldb_private::CommandInterpreter *interpreter,
|
|
SearchFilter *searcher,
|
|
lldb_private::StringList &matches)
|
|
{
|
|
ModuleCompleter completer(partial_file_name, match_start_point, max_return_elements, interpreter, matches);
|
|
|
|
if (searcher == NULL)
|
|
{
|
|
lldb::TargetSP target_sp = interpreter->Context()->GetTarget()->GetSP();
|
|
SearchFilter null_searcher (target_sp);
|
|
completer.DoCompletion (&null_searcher);
|
|
}
|
|
else
|
|
{
|
|
completer.DoCompletion (searcher);
|
|
}
|
|
return matches.GetSize();
|
|
}
|
|
|
|
int
|
|
CommandCompletions::Symbols (const char *partial_file_name,
|
|
int match_start_point,
|
|
int max_return_elements,
|
|
lldb_private::CommandInterpreter *interpreter,
|
|
SearchFilter *searcher,
|
|
lldb_private::StringList &matches)
|
|
{
|
|
SymbolCompleter completer(partial_file_name, match_start_point, max_return_elements, interpreter, matches);
|
|
|
|
if (searcher == NULL)
|
|
{
|
|
lldb::TargetSP target_sp = interpreter->Context()->GetTarget()->GetSP();
|
|
SearchFilter null_searcher (target_sp);
|
|
completer.DoCompletion (&null_searcher);
|
|
}
|
|
else
|
|
{
|
|
completer.DoCompletion (searcher);
|
|
}
|
|
return matches.GetSize();
|
|
}
|
|
|
|
CommandCompletions::Completer::Completer (
|
|
const char *completion_str,
|
|
int match_start_point,
|
|
int max_return_elements,
|
|
CommandInterpreter *interpreter,
|
|
StringList &matches
|
|
) :
|
|
m_completion_str (completion_str),
|
|
m_match_start_point (match_start_point),
|
|
m_max_return_elements (max_return_elements),
|
|
m_interpreter (interpreter),
|
|
m_matches (matches)
|
|
{
|
|
}
|
|
|
|
CommandCompletions::Completer::~Completer ()
|
|
{
|
|
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// SourceFileCompleter
|
|
//----------------------------------------------------------------------
|
|
|
|
CommandCompletions::SourceFileCompleter::SourceFileCompleter (
|
|
bool include_support_files,
|
|
const char *completion_str,
|
|
int match_start_point,
|
|
int max_return_elements,
|
|
CommandInterpreter *interpreter,
|
|
StringList &matches
|
|
) :
|
|
CommandCompletions::Completer (completion_str, match_start_point, max_return_elements, interpreter, matches),
|
|
m_include_support_files (include_support_files),
|
|
m_matching_files()
|
|
{
|
|
FileSpec partial_spec (m_completion_str.c_str());
|
|
m_file_name = partial_spec.GetFilename().GetCString();
|
|
m_dir_name = partial_spec.GetDirectory().GetCString();
|
|
}
|
|
|
|
Searcher::Depth
|
|
CommandCompletions::SourceFileCompleter::GetDepth()
|
|
{
|
|
return eDepthCompUnit;
|
|
}
|
|
|
|
Searcher::CallbackReturn
|
|
CommandCompletions::SourceFileCompleter::SearchCallback (
|
|
SearchFilter &filter,
|
|
SymbolContext &context,
|
|
Address *addr,
|
|
bool complete
|
|
)
|
|
{
|
|
if (context.comp_unit != NULL)
|
|
{
|
|
if (m_include_support_files)
|
|
{
|
|
FileSpecList supporting_files = context.comp_unit->GetSupportFiles();
|
|
for (size_t sfiles = 0; sfiles < supporting_files.GetSize(); sfiles++)
|
|
{
|
|
const FileSpec &sfile_spec = supporting_files.GetFileSpecAtIndex(sfiles);
|
|
const char *sfile_file_name = sfile_spec.GetFilename().GetCString();
|
|
const char *sfile_dir_name = sfile_spec.GetFilename().GetCString();
|
|
bool match = false;
|
|
if (m_file_name && sfile_file_name
|
|
&& strstr (sfile_file_name, m_file_name) == sfile_file_name)
|
|
match = true;
|
|
if (match && m_dir_name && sfile_dir_name
|
|
&& strstr (sfile_dir_name, m_dir_name) != sfile_dir_name)
|
|
match = false;
|
|
|
|
if (match)
|
|
{
|
|
m_matching_files.AppendIfUnique(sfile_spec);
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
const char *cur_file_name = context.comp_unit->GetFilename().GetCString();
|
|
const char *cur_dir_name = context.comp_unit->GetDirectory().GetCString();
|
|
|
|
bool match = false;
|
|
if (m_file_name && cur_file_name
|
|
&& strstr (cur_file_name, m_file_name) == cur_file_name)
|
|
match = true;
|
|
|
|
if (match && m_dir_name && cur_dir_name
|
|
&& strstr (cur_dir_name, m_dir_name) != cur_dir_name)
|
|
match = false;
|
|
|
|
if (match)
|
|
{
|
|
m_matching_files.AppendIfUnique(context.comp_unit);
|
|
}
|
|
}
|
|
}
|
|
return Searcher::eCallbackReturnContinue;
|
|
}
|
|
|
|
size_t
|
|
CommandCompletions::SourceFileCompleter::DoCompletion (SearchFilter *filter)
|
|
{
|
|
filter->Search (*this);
|
|
// Now convert the filelist to completions:
|
|
for (size_t i = 0; i < m_matching_files.GetSize(); i++)
|
|
{
|
|
m_matches.AppendString (m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString());
|
|
}
|
|
return m_matches.GetSize();
|
|
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// SymbolCompleter
|
|
//----------------------------------------------------------------------
|
|
|
|
static bool
|
|
regex_chars (const char comp)
|
|
{
|
|
if (comp == '[' || comp == ']' || comp == '(' || comp == ')')
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
CommandCompletions::SymbolCompleter::SymbolCompleter (
|
|
const char *completion_str,
|
|
int match_start_point,
|
|
int max_return_elements,
|
|
CommandInterpreter *interpreter,
|
|
StringList &matches
|
|
) :
|
|
CommandCompletions::Completer (completion_str, match_start_point, max_return_elements, interpreter, matches)
|
|
{
|
|
std::string regex_str ("^");
|
|
regex_str.append(completion_str);
|
|
regex_str.append(".*");
|
|
std::string::iterator pos;
|
|
|
|
pos = find_if(regex_str.begin(), regex_str.end(), regex_chars);
|
|
while (pos < regex_str.end()) {
|
|
pos = regex_str.insert(pos, '\\');
|
|
pos += 2;
|
|
pos = find_if(pos, regex_str.end(), regex_chars);
|
|
}
|
|
m_regex.Compile(regex_str.c_str());
|
|
}
|
|
|
|
Searcher::Depth
|
|
CommandCompletions::SymbolCompleter::GetDepth()
|
|
{
|
|
return eDepthModule;
|
|
}
|
|
|
|
Searcher::CallbackReturn
|
|
CommandCompletions::SymbolCompleter::SearchCallback (
|
|
SearchFilter &filter,
|
|
SymbolContext &context,
|
|
Address *addr,
|
|
bool complete
|
|
)
|
|
{
|
|
SymbolContextList func_list;
|
|
SymbolContextList sym_list;
|
|
|
|
if (context.module_sp != NULL)
|
|
{
|
|
if (context.module_sp)
|
|
{
|
|
context.module_sp->FindSymbolsMatchingRegExAndType (m_regex, lldb::eSymbolTypeCode, sym_list);
|
|
context.module_sp->FindFunctions (m_regex, true, func_list);
|
|
}
|
|
|
|
SymbolContext sc;
|
|
// Now add the functions & symbols to the list - only add if unique:
|
|
for (int i = 0; i < func_list.GetSize(); i++)
|
|
{
|
|
if (func_list.GetContextAtIndex(i, sc))
|
|
{
|
|
if (sc.function)
|
|
{
|
|
m_match_set.insert (sc.function->GetMangled().GetDemangledName());
|
|
}
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < sym_list.GetSize(); i++)
|
|
{
|
|
if (sym_list.GetContextAtIndex(i, sc))
|
|
{
|
|
if (sc.symbol && sc.symbol->GetAddressRangePtr())
|
|
{
|
|
m_match_set.insert (sc.symbol->GetMangled().GetDemangledName());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return Searcher::eCallbackReturnContinue;
|
|
}
|
|
|
|
size_t
|
|
CommandCompletions::SymbolCompleter::DoCompletion (SearchFilter *filter)
|
|
{
|
|
filter->Search (*this);
|
|
collection::iterator pos = m_match_set.begin(), end = m_match_set.end();
|
|
for (pos = m_match_set.begin(); pos != end; pos++)
|
|
m_matches.AppendString((*pos).GetCString());
|
|
|
|
return m_matches.GetSize();
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// ModuleCompleter
|
|
//----------------------------------------------------------------------
|
|
CommandCompletions::ModuleCompleter::ModuleCompleter (
|
|
const char *completion_str,
|
|
int match_start_point,
|
|
int max_return_elements,
|
|
CommandInterpreter *interpreter,
|
|
StringList &matches
|
|
) :
|
|
CommandCompletions::Completer (completion_str, match_start_point, max_return_elements, interpreter, matches)
|
|
{
|
|
FileSpec partial_spec (m_completion_str.c_str());
|
|
m_file_name = partial_spec.GetFilename().GetCString();
|
|
m_dir_name = partial_spec.GetDirectory().GetCString();
|
|
}
|
|
|
|
Searcher::Depth
|
|
CommandCompletions::ModuleCompleter::GetDepth()
|
|
{
|
|
return eDepthModule;
|
|
}
|
|
|
|
Searcher::CallbackReturn
|
|
CommandCompletions::ModuleCompleter::SearchCallback (
|
|
SearchFilter &filter,
|
|
SymbolContext &context,
|
|
Address *addr,
|
|
bool complete
|
|
)
|
|
{
|
|
if (context.module_sp != NULL)
|
|
{
|
|
const char *cur_file_name = context.module_sp->GetFileSpec().GetFilename().GetCString();
|
|
const char *cur_dir_name = context.module_sp->GetFileSpec().GetDirectory().GetCString();
|
|
|
|
bool match = false;
|
|
if (m_file_name && cur_file_name
|
|
&& strstr (cur_file_name, m_file_name) == cur_file_name)
|
|
match = true;
|
|
|
|
if (match && m_dir_name && cur_dir_name
|
|
&& strstr (cur_dir_name, m_dir_name) != cur_dir_name)
|
|
match = false;
|
|
|
|
if (match)
|
|
{
|
|
m_matches.AppendString (cur_file_name);
|
|
}
|
|
}
|
|
return Searcher::eCallbackReturnContinue;
|
|
}
|
|
|
|
size_t
|
|
CommandCompletions::ModuleCompleter::DoCompletion (SearchFilter *filter)
|
|
{
|
|
filter->Search (*this);
|
|
return m_matches.GetSize();
|
|
}
|
|
|
|
|
|
|