forked from OSchip/llvm-project
Added an error message when the user tries to add a filter when a synthetic provider for the same type is already defined in the same category
The converse is also true: an error is shown when the user tries to add a synthetic provider to a category that already has a filter for the same type llvm-svn: 137493
This commit is contained in:
parent
70cb84a0f6
commit
68eb4bb421
|
@ -512,9 +512,16 @@ public:
|
|||
lldb::DynamicValueType use_dynamic,
|
||||
lldb::SummaryFormatSP& entry);
|
||||
static bool
|
||||
GetSyntheticFilter(ValueObject& vobj,
|
||||
lldb::DynamicValueType use_dynamic,
|
||||
lldb::SyntheticChildrenSP& entry);
|
||||
GetSyntheticChildren(ValueObject& vobj,
|
||||
lldb::DynamicValueType use_dynamic,
|
||||
lldb::SyntheticChildrenSP& entry);
|
||||
|
||||
static bool
|
||||
AnyMatches(ConstString type_name,
|
||||
FormatCategory::FormatCategoryItems items = FormatCategory::ALL_ITEM_TYPES,
|
||||
bool only_enabled = true,
|
||||
const char** matching_category = NULL,
|
||||
FormatCategory::FormatCategoryItems* matching_type = NULL);
|
||||
|
||||
class NamedSummaryFormats
|
||||
{
|
||||
|
|
|
@ -608,8 +608,10 @@ class CategoryMap;
|
|||
class FormatCategory
|
||||
{
|
||||
private:
|
||||
|
||||
typedef FormatNavigator<const char*, SummaryFormat> SummaryNavigator;
|
||||
typedef FormatNavigator<lldb::RegularExpressionSP, SummaryFormat> RegexSummaryNavigator;
|
||||
|
||||
typedef FormatNavigator<const char*, SyntheticFilter> FilterNavigator;
|
||||
typedef FormatNavigator<lldb::RegularExpressionSP, SyntheticFilter> RegexFilterNavigator;
|
||||
|
||||
|
@ -655,6 +657,15 @@ private:
|
|||
|
||||
friend class CategoryMap;
|
||||
|
||||
friend class FormatNavigator<const char*, SummaryFormat>;
|
||||
friend class FormatNavigator<lldb::RegularExpressionSP, SummaryFormat>;
|
||||
|
||||
friend class FormatNavigator<const char*, SyntheticFilter>;
|
||||
friend class FormatNavigator<lldb::RegularExpressionSP, SyntheticFilter>;
|
||||
|
||||
friend class FormatNavigator<const char*, SyntheticScriptProvider>;
|
||||
friend class FormatNavigator<lldb::RegularExpressionSP, SyntheticScriptProvider>;
|
||||
|
||||
public:
|
||||
|
||||
enum FormatCategoryItem
|
||||
|
@ -824,17 +835,17 @@ public:
|
|||
void
|
||||
Clear(FormatCategoryItems items = ALL_ITEM_TYPES)
|
||||
{
|
||||
if ( (items & eSummary) )
|
||||
if ( (items & eSummary) == eSummary )
|
||||
m_summary_nav->Clear();
|
||||
if ( (items & eRegexSummary) )
|
||||
if ( (items & eRegexSummary) == eRegexSummary )
|
||||
m_regex_summary_nav->Clear();
|
||||
if ( (items & eFilter) )
|
||||
if ( (items & eFilter) == eFilter )
|
||||
m_filter_nav->Clear();
|
||||
if ( (items & eRegexFilter) )
|
||||
if ( (items & eRegexFilter) == eRegexFilter )
|
||||
m_regex_filter_nav->Clear();
|
||||
if ( (items & eSynth) )
|
||||
if ( (items & eSynth) == eSynth )
|
||||
m_synth_nav->Clear();
|
||||
if ( (items & eRegexSynth) )
|
||||
if ( (items & eRegexSynth) == eRegexSynth )
|
||||
m_regex_synth_nav->Clear();
|
||||
}
|
||||
|
||||
|
@ -843,17 +854,17 @@ public:
|
|||
FormatCategoryItems items = ALL_ITEM_TYPES)
|
||||
{
|
||||
bool success = false;
|
||||
if ( (items & eSummary) )
|
||||
if ( (items & eSummary) == eSummary )
|
||||
success = m_summary_nav->Delete(name) || success;
|
||||
if ( (items & eRegexSummary) )
|
||||
if ( (items & eRegexSummary) == eRegexSummary )
|
||||
success = m_regex_summary_nav->Delete(name) || success;
|
||||
if ( (items & eFilter) )
|
||||
if ( (items & eFilter) == eFilter )
|
||||
success = m_filter_nav->Delete(name) || success;
|
||||
if ( (items & eRegexFilter) )
|
||||
if ( (items & eRegexFilter) == eRegexFilter )
|
||||
success = m_regex_filter_nav->Delete(name) || success;
|
||||
if ( (items & eSynth) )
|
||||
if ( (items & eSynth) == eSynth )
|
||||
success = m_synth_nav->Delete(name) || success;
|
||||
if ( (items & eRegexSynth) )
|
||||
if ( (items & eRegexSynth) == eRegexSynth )
|
||||
success = m_regex_synth_nav->Delete(name) || success;
|
||||
return success;
|
||||
}
|
||||
|
@ -862,17 +873,17 @@ public:
|
|||
GetCount(FormatCategoryItems items = ALL_ITEM_TYPES)
|
||||
{
|
||||
uint32_t count = 0;
|
||||
if ( (items & eSummary) )
|
||||
if ( (items & eSummary) == eSummary )
|
||||
count += m_summary_nav->GetCount();
|
||||
if ( (items & eRegexSummary) )
|
||||
if ( (items & eRegexSummary) == eRegexSummary )
|
||||
count += m_regex_summary_nav->GetCount();
|
||||
if ( (items & eFilter) )
|
||||
if ( (items & eFilter) == eFilter )
|
||||
count += m_filter_nav->GetCount();
|
||||
if ( (items & eRegexFilter) )
|
||||
if ( (items & eRegexFilter) == eRegexFilter )
|
||||
count += m_regex_filter_nav->GetCount();
|
||||
if ( (items & eSynth) )
|
||||
if ( (items & eSynth) == eSynth )
|
||||
count += m_synth_nav->GetCount();
|
||||
if ( (items & eRegexSynth) )
|
||||
if ( (items & eRegexSynth) == eRegexSynth )
|
||||
count += m_regex_synth_nav->GetCount();
|
||||
return count;
|
||||
}
|
||||
|
@ -883,6 +894,89 @@ public:
|
|||
return m_name;
|
||||
}
|
||||
|
||||
bool
|
||||
AnyMatches(ConstString type_name,
|
||||
FormatCategoryItems items = ALL_ITEM_TYPES,
|
||||
bool only_enabled = true,
|
||||
const char** matching_category = NULL,
|
||||
FormatCategoryItems* matching_type = NULL)
|
||||
{
|
||||
if (!IsEnabled() && only_enabled)
|
||||
return false;
|
||||
|
||||
SummaryFormat::SharedPointer summary;
|
||||
SyntheticFilter::SharedPointer filter;
|
||||
SyntheticScriptProvider::SharedPointer synth;
|
||||
|
||||
if ( (items & eSummary) == eSummary )
|
||||
{
|
||||
if (m_summary_nav->Get(type_name.AsCString(), summary))
|
||||
{
|
||||
if (matching_category)
|
||||
*matching_category = m_name.c_str();
|
||||
if (matching_type)
|
||||
*matching_type = eSummary;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if ( (items & eRegexSummary) == eRegexSummary )
|
||||
{
|
||||
if (m_regex_summary_nav->Get(type_name.AsCString(), summary))
|
||||
{
|
||||
if (matching_category)
|
||||
*matching_category = m_name.c_str();
|
||||
if (matching_type)
|
||||
*matching_type = eRegexSummary;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if ( (items & eFilter) == eFilter )
|
||||
{
|
||||
if (m_filter_nav->Get(type_name.AsCString(), filter))
|
||||
{
|
||||
if (matching_category)
|
||||
*matching_category = m_name.c_str();
|
||||
if (matching_type)
|
||||
*matching_type = eFilter;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if ( (items & eRegexFilter) == eRegexFilter )
|
||||
{
|
||||
if (m_regex_filter_nav->Get(type_name.AsCString(), filter))
|
||||
{
|
||||
if (matching_category)
|
||||
*matching_category = m_name.c_str();
|
||||
if (matching_type)
|
||||
*matching_type = eRegexFilter;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if ( (items & eSynth) == eSynth )
|
||||
{
|
||||
if (m_synth_nav->Get(type_name.AsCString(), synth))
|
||||
{
|
||||
if (matching_category)
|
||||
*matching_category = m_name.c_str();
|
||||
if (matching_type)
|
||||
*matching_type = eSynth;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if ( (items & eRegexSynth) == eRegexSynth )
|
||||
{
|
||||
if (m_regex_synth_nav->Get(type_name.AsCString(), synth))
|
||||
{
|
||||
if (matching_category)
|
||||
*matching_category = m_name.c_str();
|
||||
if (matching_type)
|
||||
*matching_type = eRegexSynth;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
typedef lldb::SharedPtr<FormatCategory>::Type SharedPointer;
|
||||
};
|
||||
|
||||
|
@ -1052,6 +1146,28 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
AnyMatches(ConstString type_name,
|
||||
FormatCategory::FormatCategoryItems items = FormatCategory::ALL_ITEM_TYPES,
|
||||
bool only_enabled = true,
|
||||
const char** matching_category = NULL,
|
||||
FormatCategory::FormatCategoryItems* matching_type = NULL)
|
||||
{
|
||||
Mutex::Locker(m_map_mutex);
|
||||
|
||||
MapIterator pos, end = m_map.end();
|
||||
for (pos = m_map.begin(); pos != end; pos++)
|
||||
{
|
||||
if (pos->second->AnyMatches(type_name,
|
||||
items,
|
||||
only_enabled,
|
||||
matching_category,
|
||||
matching_type))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
GetCount()
|
||||
{
|
||||
|
@ -1265,6 +1381,20 @@ public:
|
|||
{
|
||||
return m_categories_map.Get(vobj, entry, use_dynamic);
|
||||
}
|
||||
|
||||
bool
|
||||
AnyMatches(ConstString type_name,
|
||||
FormatCategory::FormatCategoryItems items = FormatCategory::ALL_ITEM_TYPES,
|
||||
bool only_enabled = true,
|
||||
const char** matching_category = NULL,
|
||||
FormatCategory::FormatCategoryItems* matching_type = NULL)
|
||||
{
|
||||
return m_categories_map.AnyMatches(type_name,
|
||||
items,
|
||||
only_enabled,
|
||||
matching_category,
|
||||
matching_type);
|
||||
}
|
||||
|
||||
static bool
|
||||
GetFormatFromCString (const char *format_cstr,
|
||||
|
|
|
@ -3018,15 +3018,24 @@ public:
|
|||
lldb::FormatCategorySP category;
|
||||
Debugger::Formatting::Categories::Get(ConstString(options->m_category.c_str()), category);
|
||||
|
||||
Error error;
|
||||
|
||||
for (size_t i = 0; i < options->m_target_types.GetSize(); i++) {
|
||||
const char *type_name = options->m_target_types.GetStringAtIndex(i);
|
||||
ConstString typeCS(type_name);
|
||||
if (typeCS)
|
||||
CommandObjectTypeSynthAdd::AddSynth(typeCS,
|
||||
synth_provider,
|
||||
options->m_regex ? CommandObjectTypeSynthAdd::eRegexSynth : CommandObjectTypeSynthAdd::eRegularSynth,
|
||||
options->m_category,
|
||||
NULL);
|
||||
{
|
||||
if (!CommandObjectTypeSynthAdd::AddSynth(typeCS,
|
||||
synth_provider,
|
||||
options->m_regex ? CommandObjectTypeSynthAdd::eRegexSynth : CommandObjectTypeSynthAdd::eRegularSynth,
|
||||
options->m_category,
|
||||
&error))
|
||||
{
|
||||
out_stream->Printf("%s\n", error.AsCString());
|
||||
out_stream->Flush();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
out_stream->Printf ("Internal error #6: no script attached.\n");
|
||||
|
@ -3126,15 +3135,24 @@ CommandObjectTypeSynthAdd::Execute_PythonClass (Args& command, CommandReturnObje
|
|||
lldb::FormatCategorySP category;
|
||||
Debugger::Formatting::Categories::Get(ConstString(m_options.m_category.c_str()), category);
|
||||
|
||||
Error error;
|
||||
|
||||
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);
|
||||
{
|
||||
if (!AddSynth(typeCS,
|
||||
entry,
|
||||
m_options.m_regex ? eRegexSynth : eRegularSynth,
|
||||
m_options.m_category,
|
||||
&error))
|
||||
{
|
||||
result.AppendError(error.AsCString());
|
||||
result.SetStatus(eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendError("empty typenames not allowed");
|
||||
|
@ -3175,6 +3193,15 @@ CommandObjectTypeSynthAdd::AddSynth(const ConstString& type_name,
|
|||
lldb::FormatCategorySP category;
|
||||
Debugger::Formatting::Categories::Get(ConstString(category_name.c_str()), category);
|
||||
|
||||
if (category->AnyMatches(type_name,
|
||||
FormatCategory::eFilter | FormatCategory::eRegexFilter,
|
||||
false))
|
||||
{
|
||||
if (error)
|
||||
error->SetErrorStringWithFormat("cannot add synthetic for type %s when filter is defined in same category!", type_name.AsCString());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (type == eRegexSynth)
|
||||
{
|
||||
RegularExpressionSP typeRX(new RegularExpression());
|
||||
|
@ -3327,23 +3354,32 @@ private:
|
|||
return &m_options;
|
||||
}
|
||||
|
||||
enum SynthFormatType
|
||||
enum FilterFormatType
|
||||
{
|
||||
eRegularSynth,
|
||||
eRegexSynth,
|
||||
eRegularFilter,
|
||||
eRegexFilter,
|
||||
};
|
||||
|
||||
bool
|
||||
AddSynth(const ConstString& type_name,
|
||||
SyntheticChildrenSP entry,
|
||||
SynthFormatType type,
|
||||
std::string category_name,
|
||||
Error* error)
|
||||
AddFilter(const ConstString& type_name,
|
||||
SyntheticChildrenSP entry,
|
||||
FilterFormatType type,
|
||||
std::string category_name,
|
||||
Error* error)
|
||||
{
|
||||
lldb::FormatCategorySP category;
|
||||
Debugger::Formatting::Categories::Get(ConstString(category_name.c_str()), category);
|
||||
|
||||
if (type == eRegexSynth)
|
||||
if (category->AnyMatches(type_name,
|
||||
FormatCategory::eSynth | FormatCategory::eRegexSynth,
|
||||
false))
|
||||
{
|
||||
if (error)
|
||||
error->SetErrorStringWithFormat("cannot add filter for type %s when synthetic is defined in same category!", type_name.AsCString());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (type == eRegexFilter)
|
||||
{
|
||||
RegularExpressionSP typeRX(new RegularExpression());
|
||||
if (!typeRX->Compile(type_name.GetCString()))
|
||||
|
@ -3430,15 +3466,24 @@ public:
|
|||
lldb::FormatCategorySP category;
|
||||
Debugger::Formatting::Categories::Get(ConstString(m_options.m_category.c_str()), category);
|
||||
|
||||
Error error;
|
||||
|
||||
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);
|
||||
{
|
||||
if (!AddFilter(typeCS,
|
||||
entry,
|
||||
m_options.m_regex ? eRegexFilter : eRegularFilter,
|
||||
m_options.m_category,
|
||||
&error))
|
||||
{
|
||||
result.AppendError(error.AsCString());
|
||||
result.SetStatus(eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendError("empty typenames not allowed");
|
||||
|
|
|
@ -1837,13 +1837,27 @@ Debugger::Formatting::GetSummaryFormat(ValueObject& vobj,
|
|||
return GetFormatManager().Get(vobj, entry, use_dynamic);
|
||||
}
|
||||
bool
|
||||
Debugger::Formatting::GetSyntheticFilter(ValueObject& vobj,
|
||||
lldb::DynamicValueType use_dynamic,
|
||||
lldb::SyntheticChildrenSP& entry)
|
||||
Debugger::Formatting::GetSyntheticChildren(ValueObject& vobj,
|
||||
lldb::DynamicValueType use_dynamic,
|
||||
lldb::SyntheticChildrenSP& entry)
|
||||
{
|
||||
return GetFormatManager().Get(vobj, entry, use_dynamic);
|
||||
}
|
||||
|
||||
bool
|
||||
Debugger::Formatting::AnyMatches(ConstString type_name,
|
||||
FormatCategory::FormatCategoryItems items,
|
||||
bool only_enabled,
|
||||
const char** matching_category,
|
||||
FormatCategory::FormatCategoryItems* matching_type)
|
||||
{
|
||||
return GetFormatManager().AnyMatches(type_name,
|
||||
items,
|
||||
only_enabled,
|
||||
matching_category,
|
||||
matching_type);
|
||||
}
|
||||
|
||||
bool
|
||||
Debugger::Formatting::Categories::Get(const ConstString &category, lldb::FormatCategorySP &entry)
|
||||
{
|
||||
|
|
|
@ -243,7 +243,7 @@ ValueObject::UpdateFormatsIfNeeded(lldb::DynamicValueType use_dynamic)
|
|||
|
||||
Debugger::Formatting::ValueFormats::Get(*this, lldb::eNoDynamicValues, m_last_value_format);
|
||||
Debugger::Formatting::GetSummaryFormat(*this, use_dynamic, m_last_summary_format);
|
||||
Debugger::Formatting::GetSyntheticFilter(*this, use_dynamic, m_last_synthetic_filter);
|
||||
Debugger::Formatting::GetSyntheticChildren(*this, use_dynamic, m_last_synthetic_filter);
|
||||
|
||||
m_last_format_mgr_revision = Debugger::Formatting::ValueFormats::GetCurrentRevision();
|
||||
m_last_format_mgr_dynamic = use_dynamic;
|
||||
|
|
|
@ -136,18 +136,48 @@ class DataFormatterTestCase(TestBase):
|
|||
'fake_a = 218103808',
|
||||
'a = 12'])
|
||||
|
||||
# now mix synth and filter and check consistent output
|
||||
self.runCmd("type filter add foo --child b --child j")
|
||||
self.expect('frame variable f00_1',
|
||||
# now add a filter.. it should fail
|
||||
self.expect("type filter add foo --child b --child j", error=True,
|
||||
substrs = ['cannot add'])
|
||||
|
||||
# we get the synth again..
|
||||
self.expect('frame variable f00_1', matching=False,
|
||||
substrs = ['b = 1',
|
||||
'j = 17'])
|
||||
self.expect("frame variable -P 1 f00_ptr",
|
||||
substrs = ['r = 45',
|
||||
'fake_a = 218103808',
|
||||
'a = 12'])
|
||||
|
||||
# now delete the synth and add the filter
|
||||
self.runCmd("type synth delete foo")
|
||||
self.runCmd("type filter add foo --child b --child j")
|
||||
|
||||
self.expect('frame variable f00_1',
|
||||
substrs = ['b = 1',
|
||||
'j = 17'])
|
||||
self.expect("frame variable -P 1 f00_ptr", matching=False,
|
||||
substrs = ['r = 45',
|
||||
'fake_a = 218103808',
|
||||
'a = 12'])
|
||||
|
||||
# now add the synth again to see that it prevails
|
||||
# now add the synth and it should fail
|
||||
self.expect("type synth add -l fooSynthProvider foo", error=True,
|
||||
substrs = ['cannot add'])
|
||||
|
||||
# check the listing
|
||||
self.expect('type synth list', matching=False,
|
||||
substrs = ['foo',
|
||||
'Python class fooSynthProvider'])
|
||||
self.expect('type filter list',
|
||||
substrs = ['foo',
|
||||
'.b',
|
||||
'.j'])
|
||||
|
||||
# delete the filter, add the synth
|
||||
self.runCmd("type filter delete foo")
|
||||
self.runCmd("type synth add -l fooSynthProvider foo")
|
||||
|
||||
self.expect('frame variable f00_1', matching=False,
|
||||
substrs = ['b = 1',
|
||||
'j = 17'])
|
||||
|
@ -160,7 +190,7 @@ class DataFormatterTestCase(TestBase):
|
|||
self.expect('type synth list',
|
||||
substrs = ['foo',
|
||||
'Python class fooSynthProvider'])
|
||||
self.expect('type filter list',
|
||||
self.expect('type filter list', matching=False,
|
||||
substrs = ['foo',
|
||||
'.b',
|
||||
'.j'])
|
||||
|
@ -168,19 +198,6 @@ class DataFormatterTestCase(TestBase):
|
|||
# delete the synth and check that we get good output
|
||||
self.runCmd("type synth delete foo")
|
||||
|
||||
# first let the filter win
|
||||
self.expect('frame variable f00_1',
|
||||
substrs = ['b = 1',
|
||||
'j = 17'])
|
||||
self.expect("frame variable -P 1 f00_ptr", matching=False,
|
||||
substrs = ['r = 45',
|
||||
'fake_a = 218103808',
|
||||
'a = 12'])
|
||||
|
||||
# then delete the filter
|
||||
self.runCmd("type filter delete foo")
|
||||
|
||||
# and show real children
|
||||
self.expect("frame variable f00_1",
|
||||
substrs = ['a = 280',
|
||||
'b = 1',
|
||||
|
@ -451,7 +468,11 @@ class DataFormatterTestCase(TestBase):
|
|||
self.runCmd("frame variable ii -T")
|
||||
|
||||
self.runCmd("script from StdMapSynthProvider import *")
|
||||
self.runCmd("type summary add -x \"std::map<\" -f \"map has ${svar%#} items\" -e")
|
||||
self.runCmd("type summary add -x \"std::map<\" -f \"map has ${svar%#} items\" -e")
|
||||
|
||||
#import time
|
||||
#time.sleep(30)
|
||||
|
||||
self.runCmd("type synth add -x \"std::map<\" -l StdMapSynthProvider")
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue