blob: a299ffb098f1e2841b82ca3a0f533a85a49bbca1 [file] [log] [blame]
//===-- 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/Core/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();
}