Option --regex (-x) now also works for synthetic children:

- Added a test case in python-synth
Minor code improvements in categories, making them ready for adding new element types

llvm-svn: 136957
This commit is contained in:
Enrico Granata 2011-08-05 01:32:50 +00:00
parent 2536b51aae
commit f1af1ed6d2
5 changed files with 464 additions and 319 deletions

View File

@ -632,6 +632,17 @@ private:
public:
enum FormatCategoryItem
{
eSummary = 0x0001,
eRegexSummary = 0x1001,
eFilter = 0x0002,
eRegexFilter = 0x1002,
};
typedef uint16_t FormatCategoryItems;
static const uint16_t ALL_ITEM_TYPES = 0xFFFF;
typedef SummaryNavigator::SharedPointer SummaryNavigatorSP;
typedef RegexSummaryNavigator::SharedPointer RegexSummaryNavigatorSP;
typedef FilterNavigator::SharedPointer FilterNavigatorSP;
@ -715,24 +726,59 @@ public:
void
ClearSummaries()
{
m_summary_nav->Clear();
m_regex_summary_nav->Clear();
Clear(eSummary | eRegexSummary);
}
// just a shortcut for (Summary()->Delete(name) || RegexSummary()->Delete(name))
bool
DeleteSummaries(const char* name)
{
bool del_sum = m_summary_nav->Delete(name);
bool del_rex = m_regex_summary_nav->Delete(name);
return (del_sum || del_rex);
return Delete(name, (eSummary | eRegexSummary));
}
void
Clear(FormatCategoryItems items = ALL_ITEM_TYPES)
{
if ( (items & eSummary) )
m_summary_nav->Clear();
if ( (items & eRegexSummary) )
m_regex_summary_nav->Clear();
if ( (items & eFilter) )
m_filter_nav->Clear();
if ( (items & eRegexFilter) )
m_regex_filter_nav->Clear();
}
bool
Delete(const char* name,
FormatCategoryItems items = ALL_ITEM_TYPES)
{
bool success = false;
if ( (items & eSummary) )
success = m_summary_nav->Delete(name) || success;
if ( (items & eRegexSummary) )
success = m_regex_summary_nav->Delete(name) || success;
if ( (items & eFilter) )
success = m_filter_nav->Delete(name) || success;
if ( (items & eRegexFilter) )
success = m_regex_filter_nav->Delete(name) || success;
return success;
}
uint32_t
GetCount()
GetCount(FormatCategoryItems items = ALL_ITEM_TYPES)
{
return Summary()->GetCount() + RegexSummary()->GetCount();
uint32_t count = 0;
if ( (items & eSummary) )
count += m_summary_nav->GetCount();
if ( (items & eRegexSummary) )
count += m_regex_summary_nav->GetCount();
if ( (items & eFilter) )
count += m_filter_nav->GetCount();
if ( (items & eRegexFilter) )
count += m_regex_filter_nav->GetCount();
return count;
}
std::string

View File

@ -1168,8 +1168,7 @@ private:
const FormatCategory::SharedPointer& cate)
{
const char* name = (const char*)param;
cate->Summary()->Delete(name);
cate->RegexSummary()->Delete(name);
cate->Delete(name, FormatCategory::eSummary | FormatCategory::eRegexSummary);
return true;
}
@ -1892,6 +1891,7 @@ public:
//-------------------------------------------------------------------------
bool CommandObjectTypeSynthList_LoopCallback(void* pt2self, const char* type, const SyntheticFilter::SharedPointer& entry);
bool CommandObjectTypeSynthRXList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SyntheticFilter::SharedPointer& entry);
class CommandObjectTypeSynthList;
@ -2044,6 +2044,12 @@ private:
cate->Filter()->LoopThrough(CommandObjectTypeSynthList_LoopCallback, param_vp);
if (cate->RegexFilter()->GetCount() > 0)
{
result->GetOutputStream().Printf("Regex-based filters (slower):\n");
cate->RegexFilter()->LoopThrough(CommandObjectTypeSynthRXList_LoopCallback, param_vp);
}
return true;
}
@ -2059,6 +2065,7 @@ private:
}
friend bool CommandObjectTypeSynthList_LoopCallback(void* pt2self, const char* type, const SyntheticFilter::SharedPointer& entry);
friend bool CommandObjectTypeSynthRXList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SyntheticFilter::SharedPointer& entry);
};
bool
@ -2070,6 +2077,15 @@ CommandObjectTypeSynthList_LoopCallback (void* pt2self,
return param->self->LoopCallback(type, entry, param->regex, param->result);
}
bool
CommandObjectTypeSynthRXList_LoopCallback (void* pt2self,
lldb::RegularExpressionSP regex,
const SyntheticFilter::SharedPointer& entry)
{
CommandObjectTypeSynthList_LoopCallbackParam* param = (CommandObjectTypeSynthList_LoopCallbackParam*)pt2self;
return param->self->LoopCallback(regex->GetText(), entry, param->regex, param->result);
}
OptionDefinition
CommandObjectTypeSynthList::CommandOptions::g_option_table[] =
@ -2157,8 +2173,7 @@ private:
const FormatCategory::SharedPointer& cate)
{
const char* name = (const char*)param;
cate->Filter()->Delete(name);
return true;
return cate->Delete(name, FormatCategory::eFilter | FormatCategory::eRegexFilter);
}
public:
@ -2217,6 +2232,7 @@ public:
Debugger::Formatting::Categories::Get(ConstString(m_options.m_category), category);
bool delete_category = category->Filter()->Delete(typeCS.GetCString());
delete_category = category->RegexFilter()->Delete(typeCS.GetCString()) || delete_category;
if (delete_category)
{
@ -2315,7 +2331,7 @@ private:
const char* cate_name,
const FormatCategory::SharedPointer& cate)
{
cate->Filter()->Clear();
cate->Clear(FormatCategory::eFilter | FormatCategory::eRegexFilter);
return true;
}
@ -2352,6 +2368,7 @@ public:
else
Debugger::Formatting::Categories::Get(ConstString(NULL), category);
category->Filter()->Clear();
category->RegexFilter()->Clear();
}
result.SetStatus(eReturnStatusSuccessFinishResult);
@ -2506,7 +2523,11 @@ public:
const char *type_name = options->m_target_types.GetStringAtIndex(i);
ConstString typeCS(type_name);
if (typeCS)
category->Filter()->Add(typeCS.GetCString(), synth_provider);
CommandObjectTypeSynthAdd::AddSynth(typeCS,
synth_provider,
options->m_regex ? CommandObjectTypeSynthAdd::eRegexSynth : CommandObjectTypeSynthAdd::eRegularSynth,
options->m_category,
NULL);
else
{
out_stream->Printf ("Internal error #6: no script attached.\n");
@ -2517,319 +2538,242 @@ public:
}
};
class CommandObjectTypeSynthAdd : public CommandObject
void
CommandObjectTypeSynthAdd::CollectPythonScript (SynthAddOptions *options,
CommandReturnObject &result)
{
private:
class CommandOptions : public Options
InputReaderSP reader_sp (new TypeSynthAddInputReader(m_interpreter.GetDebugger()));
if (reader_sp && options)
{
typedef std::vector<std::string> option_vector;
public:
CommandOptions (CommandInterpreter &interpreter) :
Options (interpreter)
InputReaderEZ::InitializationParameters ipr;
Error err (reader_sp->Initialize (ipr.SetBaton(options).SetPrompt(" ")));
if (err.Success())
{
}
virtual
~CommandOptions (){}
virtual Error
SetOptionValue (uint32_t option_idx, const char *option_arg)
{
Error error;
char short_option = (char) m_getopt_table[option_idx].val;
bool success;
switch (short_option)
{
case 'C':
m_cascade = Args::StringToBoolean(option_arg, true, &success);
if (!success)
error.SetErrorStringWithFormat("Invalid value for cascade: %s.\n", option_arg);
break;
case 'c':
m_expr_paths.push_back(option_arg);
has_child_list = true;
break;
case 'P':
handwrite_python = true;
break;
case 'l':
m_class_name = std::string(option_arg);
is_class_based = true;
break;
case 'p':
m_skip_pointers = true;
break;
case 'r':
m_skip_references = true;
break;
case 'w':
m_category = ConstString(option_arg).GetCString();
break;
default:
error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
break;
}
return error;
}
void
OptionParsingStarting ()
{
m_cascade = true;
m_class_name = "";
m_skip_pointers = false;
m_skip_references = false;
m_category = NULL;
m_expr_paths.clear();
is_class_based = false;
handwrite_python = false;
has_child_list = false;
}
const OptionDefinition*
GetDefinitions ()
{
return g_option_table;
}
// Options table: Required for subclasses of Options.
static OptionDefinition g_option_table[];
// Instance variables to hold the values for command options.
bool m_cascade;
bool m_skip_references;
bool m_skip_pointers;
std::string m_class_name;
bool m_input_python;
option_vector m_expr_paths;
const char* m_category;
bool is_class_based;
bool handwrite_python;
bool has_child_list;
typedef option_vector::iterator ExpressionPathsIterator;
};
CommandOptions m_options;
virtual Options *
GetOptions ()
{
return &m_options;
}
void
CollectPythonScript (SynthAddOptions *options,
CommandReturnObject &result)
{
InputReaderSP reader_sp (new TypeSynthAddInputReader(m_interpreter.GetDebugger()));
if (reader_sp && options)
{
InputReaderEZ::InitializationParameters ipr;
Error err (reader_sp->Initialize (ipr.SetBaton(options).SetPrompt(" ")));
if (err.Success())
{
m_interpreter.GetDebugger().PushInputReader (reader_sp);
result.SetStatus (eReturnStatusSuccessFinishNoResult);
}
else
{
result.AppendError (err.AsCString());
result.SetStatus (eReturnStatusFailed);
}
m_interpreter.GetDebugger().PushInputReader (reader_sp);
result.SetStatus (eReturnStatusSuccessFinishNoResult);
}
else
{
result.AppendError("out of memory");
result.AppendError (err.AsCString());
result.SetStatus (eReturnStatusFailed);
}
}
bool
Execute_HandwritePython (Args& command, CommandReturnObject &result)
else
{
SynthAddOptions *options = new SynthAddOptions ( m_options.m_skip_pointers,
m_options.m_skip_references,
m_options.m_cascade,
m_options.m_category);
const size_t argc = command.GetArgumentCount();
for (size_t i = 0; i < argc; i++) {
const char* typeA = command.GetArgumentAtIndex(i);
if (typeA && *typeA)
options->m_target_types << typeA;
else
{
result.AppendError("empty typenames not allowed");
result.SetStatus(eReturnStatusFailed);
return false;
}
}
CollectPythonScript(options,result);
return result.Succeeded();
result.AppendError("out of memory");
result.SetStatus (eReturnStatusFailed);
}
}
bool
Execute_ChildrenList (Args& command, CommandReturnObject &result)
{
const size_t argc = command.GetArgumentCount();
if (argc < 1)
{
result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str());
result.SetStatus(eReturnStatusFailed);
return false;
}
if (m_options.m_expr_paths.size() == 0)
{
result.AppendErrorWithFormat ("%s needs one or more children.\n", m_cmd_name.c_str());
result.SetStatus(eReturnStatusFailed);
return false;
}
SyntheticChildrenSP entry;
SyntheticFilter* impl = new SyntheticFilter(m_options.m_cascade,
m_options.m_skip_pointers,
m_options.m_skip_references);
entry.reset(impl);
// go through the expression paths
CommandOptions::ExpressionPathsIterator begin, end = m_options.m_expr_paths.end();
for (begin = m_options.m_expr_paths.begin(); begin != end; begin++)
impl->AddExpressionPath(*begin);
// now I have a valid provider, let's add it to every type
lldb::FormatCategorySP category;
Debugger::Formatting::Categories::Get(ConstString(m_options.m_category), category);
for (size_t i = 0; i < argc; i++) {
const char* typeA = command.GetArgumentAtIndex(i);
ConstString typeCS(typeA);
if (typeCS)
category->Filter()->Add(typeCS.GetCString(), entry);
else
{
result.AppendError("empty typenames not allowed");
result.SetStatus(eReturnStatusFailed);
return false;
}
}
result.SetStatus(eReturnStatusSuccessFinishNoResult);
return result.Succeeded();
}
bool
CommandObjectTypeSynthAdd::Execute_HandwritePython (Args& command, CommandReturnObject &result)
{
SynthAddOptions *options = new SynthAddOptions ( m_options.m_skip_pointers,
m_options.m_skip_references,
m_options.m_cascade,
m_options.m_regex,
m_options.m_category);
bool
Execute_PythonClass (Args& command, CommandReturnObject &result)
{
const size_t argc = command.GetArgumentCount();
if (argc < 1)
{
result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str());
result.SetStatus(eReturnStatusFailed);
return false;
}
if (m_options.m_class_name.empty() && !m_options.m_input_python)
{
result.AppendErrorWithFormat ("%s needs either a Python class name or -P to directly input Python code.\n", m_cmd_name.c_str());
result.SetStatus(eReturnStatusFailed);
return false;
}
SyntheticChildrenSP entry;
SyntheticScriptProvider* impl = new SyntheticScriptProvider(m_options.m_cascade,
m_options.m_skip_pointers,
m_options.m_skip_references,
m_options.m_class_name);
entry.reset(impl);
// now I have a valid provider, let's add it to every type
lldb::FormatCategorySP category;
Debugger::Formatting::Categories::Get(ConstString(m_options.m_category), category);
for (size_t i = 0; i < argc; i++) {
const char* typeA = command.GetArgumentAtIndex(i);
ConstString typeCS(typeA);
if (typeCS)
category->Filter()->Add(typeCS.GetCString(), entry);
else
{
result.AppendError("empty typenames not allowed");
result.SetStatus(eReturnStatusFailed);
return false;
}
}
result.SetStatus(eReturnStatusSuccessFinishNoResult);
return result.Succeeded();
}
const size_t argc = command.GetArgumentCount();
public:
CommandObjectTypeSynthAdd (CommandInterpreter &interpreter) :
CommandObject (interpreter,
"type synth add",
"Add a new synthetic provider for a type.",
NULL), m_options (interpreter)
{
CommandArgumentEntry type_arg;
CommandArgumentData type_style_arg;
type_style_arg.arg_type = eArgTypeName;
type_style_arg.arg_repetition = eArgRepeatPlus;
type_arg.push_back (type_style_arg);
m_arguments.push_back (type_arg);
}
~CommandObjectTypeSynthAdd ()
{
}
bool
Execute (Args& command, CommandReturnObject &result)
{
if (m_options.handwrite_python)
return Execute_HandwritePython(command, result);
else if (m_options.is_class_based)
return Execute_PythonClass(command, result);
else if (m_options.has_child_list)
return Execute_ChildrenList(command, result);
for (size_t i = 0; i < argc; i++) {
const char* typeA = command.GetArgumentAtIndex(i);
if (typeA && *typeA)
options->m_target_types << typeA;
else
{
result.AppendError("must either provide a children list, a Python class name, or use -P and type a Python class line-by-line");
result.AppendError("empty typenames not allowed");
result.SetStatus(eReturnStatusFailed);
return false;
}
}
};
CollectPythonScript(options,result);
return result.Succeeded();
}
bool
CommandObjectTypeSynthAdd::Execute_ChildrenList (Args& command, CommandReturnObject &result)
{
const size_t argc = command.GetArgumentCount();
if (argc < 1)
{
result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str());
result.SetStatus(eReturnStatusFailed);
return false;
}
if (m_options.m_expr_paths.size() == 0)
{
result.AppendErrorWithFormat ("%s needs one or more children.\n", m_cmd_name.c_str());
result.SetStatus(eReturnStatusFailed);
return false;
}
SyntheticChildrenSP entry;
SyntheticFilter* impl = new SyntheticFilter(m_options.m_cascade,
m_options.m_skip_pointers,
m_options.m_skip_references);
entry.reset(impl);
// go through the expression paths
CommandOptions::ExpressionPathsIterator begin, end = m_options.m_expr_paths.end();
for (begin = m_options.m_expr_paths.begin(); begin != end; begin++)
impl->AddExpressionPath(*begin);
// now I have a valid provider, let's add it to every type
lldb::FormatCategorySP category;
Debugger::Formatting::Categories::Get(ConstString(m_options.m_category), category);
for (size_t i = 0; i < argc; i++) {
const char* typeA = command.GetArgumentAtIndex(i);
ConstString typeCS(typeA);
if (typeCS)
AddSynth(typeCS,
entry,
m_options.m_regex ? eRegexSynth : eRegularSynth,
m_options.m_category,
NULL);
else
{
result.AppendError("empty typenames not allowed");
result.SetStatus(eReturnStatusFailed);
return false;
}
}
result.SetStatus(eReturnStatusSuccessFinishNoResult);
return result.Succeeded();
}
bool
CommandObjectTypeSynthAdd::Execute_PythonClass (Args& command, CommandReturnObject &result)
{
const size_t argc = command.GetArgumentCount();
if (argc < 1)
{
result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str());
result.SetStatus(eReturnStatusFailed);
return false;
}
if (m_options.m_class_name.empty() && !m_options.m_input_python)
{
result.AppendErrorWithFormat ("%s needs either a Python class name or -P to directly input Python code.\n", m_cmd_name.c_str());
result.SetStatus(eReturnStatusFailed);
return false;
}
SyntheticChildrenSP entry;
SyntheticScriptProvider* impl = new SyntheticScriptProvider(m_options.m_cascade,
m_options.m_skip_pointers,
m_options.m_skip_references,
m_options.m_class_name);
entry.reset(impl);
// now I have a valid provider, let's add it to every type
lldb::FormatCategorySP category;
Debugger::Formatting::Categories::Get(ConstString(m_options.m_category), category);
for (size_t i = 0; i < argc; i++) {
const char* typeA = command.GetArgumentAtIndex(i);
ConstString typeCS(typeA);
if (typeCS)
AddSynth(typeCS,
entry,
m_options.m_regex ? eRegexSynth : eRegularSynth,
m_options.m_category,
NULL);
else
{
result.AppendError("empty typenames not allowed");
result.SetStatus(eReturnStatusFailed);
return false;
}
}
result.SetStatus(eReturnStatusSuccessFinishNoResult);
return result.Succeeded();
}
CommandObjectTypeSynthAdd::CommandObjectTypeSynthAdd (CommandInterpreter &interpreter) :
CommandObject (interpreter,
"type synth add",
"Add a new synthetic provider for a type.",
NULL), m_options (interpreter)
{
CommandArgumentEntry type_arg;
CommandArgumentData type_style_arg;
type_style_arg.arg_type = eArgTypeName;
type_style_arg.arg_repetition = eArgRepeatPlus;
type_arg.push_back (type_style_arg);
m_arguments.push_back (type_arg);
}
bool
CommandObjectTypeSynthAdd::AddSynth(const ConstString& type_name,
SyntheticChildrenSP entry,
SynthFormatType type,
const char* category_name,
Error* error)
{
lldb::FormatCategorySP category;
Debugger::Formatting::Categories::Get(ConstString(category_name), category);
if (type == eRegexSynth)
{
RegularExpressionSP typeRX(new RegularExpression());
if (!typeRX->Compile(type_name.GetCString()))
{
if (error)
error->SetErrorString("regex format error (maybe this is not really a regex?)");
return false;
}
category->RegexFilter()->Delete(type_name.GetCString());
category->RegexFilter()->Add(typeRX, entry);
return true;
}
else
{
category->Filter()->Add(type_name.GetCString(), entry);
return true;
}
}
bool
CommandObjectTypeSynthAdd::Execute (Args& command, CommandReturnObject &result)
{
if (m_options.handwrite_python)
return Execute_HandwritePython(command, result);
else if (m_options.is_class_based)
return Execute_PythonClass(command, result);
else if (m_options.has_child_list)
return Execute_ChildrenList(command, result);
else
{
result.AppendError("must either provide a children list, a Python class name, or use -P and type a Python class line-by-line");
result.SetStatus(eReturnStatusFailed);
return false;
}
}
OptionDefinition
CommandObjectTypeSynthAdd::CommandOptions::g_option_table[] =
@ -2841,6 +2785,7 @@ CommandObjectTypeSynthAdd::CommandOptions::g_option_table[] =
{ LLDB_OPT_SET_1, false, "child", 'c', required_argument, NULL, 0, eArgTypeName, "Include this expression path in the synthetic view."},
{ LLDB_OPT_SET_2, false, "python-class", 'l', required_argument, NULL, 0, eArgTypeName, "Use this Python class to produce synthetic children."},
{ LLDB_OPT_SET_3, false, "input-python", 'P', no_argument, NULL, 0, eArgTypeNone, "Type Python code to generate a class that provides synthetic children."},
{ LLDB_OPT_SET_ALL, false, "regex", 'x', no_argument, NULL, 0, eArgTypeNone, "Type names are actually regular expressions."},
{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
};

View File

@ -78,6 +78,7 @@ public:
bool m_skip_pointers;
bool m_skip_references;
bool m_cascade;
bool m_regex;
StringList m_user_source;
StringList m_target_types;
@ -86,10 +87,12 @@ public:
SynthAddOptions(bool sptr,
bool sref,
bool casc,
bool regx,
const char* catg) :
m_skip_pointers(sptr),
m_skip_references(sref),
m_cascade(casc),
m_regex(regx),
m_user_source(),
m_target_types(),
m_category(catg)
@ -203,7 +206,157 @@ public:
const char* category,
Error* error = NULL);
};
class CommandObjectTypeSynthAdd : public CommandObject
{
private:
class CommandOptions : public Options
{
typedef std::vector<std::string> option_vector;
public:
CommandOptions (CommandInterpreter &interpreter) :
Options (interpreter)
{
}
virtual
~CommandOptions (){}
virtual Error
SetOptionValue (uint32_t option_idx, const char *option_arg)
{
Error error;
char short_option = (char) m_getopt_table[option_idx].val;
bool success;
switch (short_option)
{
case 'C':
m_cascade = Args::StringToBoolean(option_arg, true, &success);
if (!success)
error.SetErrorStringWithFormat("Invalid value for cascade: %s.\n", option_arg);
break;
case 'c':
m_expr_paths.push_back(option_arg);
has_child_list = true;
break;
case 'P':
handwrite_python = true;
break;
case 'l':
m_class_name = std::string(option_arg);
is_class_based = true;
break;
case 'p':
m_skip_pointers = true;
break;
case 'r':
m_skip_references = true;
break;
case 'w':
m_category = ConstString(option_arg).GetCString();
break;
case 'x':
m_regex = true;
break;
default:
error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
break;
}
return error;
}
void
OptionParsingStarting ()
{
m_cascade = true;
m_class_name = "";
m_skip_pointers = false;
m_skip_references = false;
m_category = NULL;
m_expr_paths.clear();
is_class_based = false;
handwrite_python = false;
has_child_list = false;
m_regex = false;
}
const OptionDefinition*
GetDefinitions ()
{
return g_option_table;
}
// Options table: Required for subclasses of Options.
static OptionDefinition g_option_table[];
// Instance variables to hold the values for command options.
bool m_cascade;
bool m_skip_references;
bool m_skip_pointers;
std::string m_class_name;
bool m_input_python;
option_vector m_expr_paths;
const char* m_category;
bool is_class_based;
bool handwrite_python;
bool has_child_list;
bool m_regex;
typedef option_vector::iterator ExpressionPathsIterator;
};
CommandOptions m_options;
virtual Options *
GetOptions ()
{
return &m_options;
}
void
CollectPythonScript (SynthAddOptions *options,
CommandReturnObject &result);
bool
Execute_HandwritePython (Args& command, CommandReturnObject &result);
bool
Execute_ChildrenList (Args& command, CommandReturnObject &result);
bool
Execute_PythonClass (Args& command, CommandReturnObject &result);
bool
Execute (Args& command, CommandReturnObject &result);
public:
enum SynthFormatType
{
eRegularSynth,
eRegexSynth,
};
CommandObjectTypeSynthAdd (CommandInterpreter &interpreter);
~CommandObjectTypeSynthAdd ()
{
}
static bool
AddSynth(const ConstString& type_name,
lldb::SyntheticChildrenSP entry,
SynthFormatType type,
const char* category_name,
Error* error);
};
} // namespace lldb_private

View File

@ -300,13 +300,14 @@ class DataFormatterTestCase(TestBase):
'[3] = \"!!!\"'])
# now std::map<K,V>
# also take a chance to test regex synth here
self.runCmd("n")
self.runCmd("frame variable ii -T")
self.runCmd("script from StdMapSynthProvider import *")
self.runCmd("type summary add std::intint_map intint_map -f \"map has ${svar%#} items\" -e")
self.runCmd("type synth add std::intint_map intint_map -l StdMapSynthProvider")
self.runCmd("type summary add -x \"std::map<\" -f \"map has ${svar%#} items\" -e")
self.runCmd("type synth add -x \"std::map<\" -l StdMapSynthProvider")
self.expect('frame variable ii',
@ -356,8 +357,8 @@ class DataFormatterTestCase(TestBase):
self.runCmd("n")
self.runCmd("frame variable si -T")
self.runCmd("type summary add std::strint_map strint_map -f \"map has ${svar%#} items\" -e")
self.runCmd("type synth add std::strint_map strint_map -l StdMapSynthProvider")
#self.runCmd("type summary add std::strint_map strint_map -f \"map has ${svar%#} items\" -e")
#self.runCmd("type synth add std::strint_map strint_map -l StdMapSynthProvider")
self.expect('frame variable si',
substrs = ['map has 0 items',
@ -400,8 +401,8 @@ class DataFormatterTestCase(TestBase):
self.runCmd("n")
self.runCmd("frame variable is -T")
self.runCmd("type summary add std::intstr_map intstr_map -f \"map has ${svar%#} items\" -e")
self.runCmd("type synth add std::intstr_map intstr_map -l StdMapSynthProvider")
#self.runCmd("type summary add std::intstr_map intstr_map -f \"map has ${svar%#} items\" -e")
#self.runCmd("type synth add std::intstr_map intstr_map -l StdMapSynthProvider")
self.expect('frame variable is',
substrs = ['map has 0 items',
@ -433,8 +434,8 @@ class DataFormatterTestCase(TestBase):
self.runCmd("n")
self.runCmd("frame variable ss -T")
self.runCmd("type summary add std::strstr_map strstr_map -f \"map has ${svar%#} items\" -e")
self.runCmd("type synth add std::strstr_map strstr_map -l StdMapSynthProvider")
#self.runCmd("type summary add std::strstr_map strstr_map -f \"map has ${svar%#} items\" -e")
#self.runCmd("type synth add std::strstr_map strstr_map -l StdMapSynthProvider")
self.expect('frame variable ss',
substrs = ['map has 0 items',

View File

@ -8,10 +8,10 @@ typedef std::vector<std::string> string_vect;
typedef std::list<int> int_list;
typedef std::list<std::string> string_list;
typedef std::map<int, int> intint_map;
typedef std::map<std::string, int> strint_map;
typedef std::map<int, std::string> intstr_map;
typedef std::map<std::string, std::string> strstr_map;
#define intint_map std::map<int, int>
#define strint_map std::map<std::string, int>
#define intstr_map std::map<int, std::string>
#define strstr_map std::map<std::string, std::string>
struct foo
{