Fix a crash bug loading DRC rules.

Also moves the clearance report to the new DRC engine.
This commit is contained in:
Jeff Young 2020-09-12 00:25:10 +01:00
parent ce2937a399
commit 8ac7288696
6 changed files with 94 additions and 33 deletions

View File

@ -315,14 +315,14 @@ bool DRC_ENGINE::CompileRules()
m_constraintMap[ id ]->provider = provider;
for( auto rule : m_rules )
for( DRC_RULE* rule : m_rules )
{
DRC_RULE_CONDITION* condition = nullptr;
bool compileOk = false;
std::vector<DRC_CONSTRAINT> matchingConstraints;
drc_dbg(7, "Scan provider %s, rule %s", provider->GetName(), rule->m_Name );
if( !rule->m_Condition->GetExpression().IsEmpty() )
if( rule->m_Condition && !rule->m_Condition->GetExpression().IsEmpty() )
{
condition = rule->m_Condition;
compileOk = condition->Compile( nullptr, 0, 0 ); // fixme
@ -375,9 +375,8 @@ bool DRC_ENGINE::CompileRules()
}
void DRC_ENGINE::RunTests( )
void DRC_ENGINE::InitEngine()
{
m_drcReport.reset( new DRC_REPORT );
m_testProviders = DRC_TEST_PROVIDER_REGISTRY::Instance().GetTestProviders();
for( auto provider : m_testProviders )
@ -388,8 +387,16 @@ void DRC_ENGINE::RunTests( )
inferLegacyRules();
CompileRules();
}
for( auto provider : m_testProviders )
void DRC_ENGINE::RunTests( )
{
InitEngine();
m_drcReport = std::make_shared<DRC_REPORT>();
for( DRC_TEST_PROVIDER* provider : m_testProviders )
{
bool skipProvider = false;
auto matchingConstraints = provider->GetMatchingConstraintIds();
@ -419,8 +426,11 @@ void DRC_ENGINE::RunTests( )
DRC_CONSTRAINT DRC_ENGINE::EvalRulesForItems( DRC_CONSTRAINT_TYPE_T aConstraintId,
BOARD_ITEM* a, BOARD_ITEM* b, PCB_LAYER_ID aLayer )
BOARD_ITEM* a, BOARD_ITEM* b, PCB_LAYER_ID aLayer,
REPORTER* aReporter )
{
#define REPORT( s ) { if( aReporter ) { aReporter->Report( s ); } }
// Local overrides take precedence
if( aConstraintId == DRC_CONSTRAINT_TYPE_CLEARANCE )
{
@ -428,50 +438,79 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRulesForItems( DRC_CONSTRAINT_TYPE_T aConstraintI
: nullptr;
BOARD_CONNECTED_ITEM* bc = b->IsConnected() ? static_cast<BOARD_CONNECTED_ITEM*>( b )
: nullptr;
int clearance = 0;
int overrideA = 0;
int overrideB = 0;
if( ac && ac->GetLocalClearanceOverrides( nullptr ) > clearance )
clearance = ac->GetLocalClearanceOverrides( &m_msg );
if( ac && ac->GetLocalClearanceOverrides( nullptr ) > 0 )
{
overrideA = ac->GetLocalClearanceOverrides( &m_msg );
if( bc && bc->GetLocalClearanceOverrides( nullptr ) > clearance )
clearance = bc->GetLocalClearanceOverrides( &m_msg );
REPORT( wxString::Format( _( "Local override on %s; clearance: %s." ),
a->GetSelectMenuText( aReporter->GetUnits() ),
StringFromValue( aReporter->GetUnits(), overrideA, true ) ) );
}
if( clearance )
if( bc && bc->GetLocalClearanceOverrides( nullptr ) > 0 )
{
overrideB = bc->GetLocalClearanceOverrides( &m_msg );
REPORT( wxString::Format( _( "Local override on %s; clearance: %s." ),
b->GetSelectMenuText( aReporter->GetUnits() ),
StringFromValue( aReporter->GetUnits(), overrideB, true ) ) );
// If both overridden, report on which wins
if( overrideA )
{
REPORT( wxString::Format( _( "Clearance: %s." ),
std::max( overrideA, overrideB ) ) );
}
}
if( overrideA || overrideB )
{
DRC_CONSTRAINT constraint( DRC_CONSTRAINT_TYPE_CLEARANCE, m_msg );
constraint.m_Value.SetMin( clearance );
constraint.m_Value.SetMin( std::max( overrideA, overrideB ) );
return constraint;
}
}
auto ruleset = m_constraintMap[ aConstraintId ];
for( const auto& rcond : ruleset->sortedConstraints )
for( const CONSTRAINT_WITH_CONDITIONS* rcond : ruleset->sortedConstraints )
{
DRC_RULE* rule = rcond->parentRule;
REPORT( wxString::Format( _( "Checking rule \"%s\"." ), rule->m_Name ) );
if( aLayer != UNDEFINED_LAYER && !rule->m_LayerCondition.test( aLayer ) )
{
REPORT( wxString::Format( _( "Rule layer \"%s\" not matched." ),
rule->m_LayerSource ) );
REPORT( "Rule not applied." );
continue;
}
if( rcond->conditions.size() == 0 ) // uconditional
{
drc_dbg( 8, " -> rule '%s' matches (unconditional)\n",
rcond->constraint.GetParentRule()->m_Name );
REPORT( "No condition found; rule applied." );
return rcond->constraint;
}
for( const auto& condition : rcond->conditions )
for( DRC_RULE_CONDITION* condition : rcond->conditions )
{
drc_dbg( 8, " -> check condition '%s'\n",
condition->GetExpression() );
REPORT( wxString::Format( _( "Checking rule condition \"%s\"." ),
condition->GetExpression() ) );
bool result = condition->EvaluateFor( a, b, aLayer );
bool result = condition->EvaluateFor( a, b, aLayer, aReporter );
REPORT( result ? _( "Rule applied." )
: _( "Condition not satisfied; rule not applied." ) );
if( result )
{
drc_dbg( 8, " -> rule '%s' matches, triggered by condition '%s'\n",
rcond->constraint.GetParentRule()->m_Name,
condition->GetExpression() );
return rcond->constraint;
}
}
}
// fixme: return optional<drc_constraint>, let the particular test decide what to do if no matching constraint
// is found

View File

@ -82,7 +82,7 @@ public:
struct ENTRY
{
std::shared_ptr<DRC_ITEM> m_item;
::MARKER_PCB* m_marker;
MARKER_PCB* m_marker;
};
typedef std::vector<ENTRY> ENTRIES;
@ -149,6 +149,8 @@ public:
m_reporter = aReporter;
}
void InitEngine();
void RunTests();
void SetErrorLimit( int aLimit );
@ -165,7 +167,8 @@ public:
DRC_CONSTRAINT EvalRulesForItems( DRC_CONSTRAINT_TYPE_T ruleID, BOARD_ITEM* a,
BOARD_ITEM* b = nullptr,
PCB_LAYER_ID aLayer = UNDEFINED_LAYER );
PCB_LAYER_ID aLayer = UNDEFINED_LAYER,
REPORTER* aReporter = nullptr );
std::vector<DRC_CONSTRAINT> QueryConstraintsById( DRC_CONSTRAINT_TYPE_T ruleID );

View File

@ -130,6 +130,7 @@ wxString DRC_CONSTRAINT::GetName() const
DRC_RULE::DRC_RULE() :
m_Unary( false ),
m_LayerCondition( LSET::AllLayersMask() ),
m_Condition( nullptr ),
m_Priority( 0 ),
m_Severity( SEVERITY::RPT_SEVERITY_ERROR )
{

View File

@ -196,7 +196,7 @@ DRC_RULE* DRC_RULES_PARSER::parseDRC_RULE()
if( IsSymbol( token ) )
{
rule->m_Condition->SetExpression( FromUTF8() );
rule->m_Condition = new DRC_RULE_CONDITION( FromUTF8() );
rule->m_Condition->Compile( m_reporter, CurLineNumber(), CurOffset() );
}
else

View File

@ -31,6 +31,7 @@
#include <connectivity/connectivity_data.h>
#include <profile.h>
#include <dialogs/wx_html_report_box.h>
#include <drc/drc_engine.h>
#include "pcb_inspection_tool.h"
@ -100,7 +101,7 @@ int PCB_INSPECTION_TOOL::ShowStatisticsDialog( const TOOL_EVENT& aEvent )
}
void reportZoneConnection( ZONE_CONTAINER* aZone, D_PAD* aPad, REPORTER* r )
void PCB_INSPECTION_TOOL::reportZoneConnection( ZONE_CONTAINER* aZone, D_PAD* aPad, REPORTER* r )
{
ENUM_MAP<ZONE_CONNECTION> connectionEnum = ENUM_MAP<ZONE_CONNECTION>::Instance();
wxString source;
@ -179,16 +180,28 @@ void reportZoneConnection( ZONE_CONTAINER* aZone, D_PAD* aPad, REPORTER* r )
}
void reportCopperClearance( PCB_LAYER_ID aLayer, BOARD_CONNECTED_ITEM* aA, BOARD_ITEM* aB,
REPORTER* r )
void PCB_INSPECTION_TOOL::reportCopperClearance( PCB_LAYER_ID aLayer, BOARD_CONNECTED_ITEM* aA,
BOARD_ITEM* aB, REPORTER* r )
{
wxString source;
r->Report( "" );
DRC_ENGINE drcEngine( m_frame->GetBoard(), &m_frame->GetBoard()->GetDesignSettings() );
drcEngine.InitEngine();
auto constraint = drcEngine.EvalRulesForItems( DRC_CONSTRAINT_TYPE_CLEARANCE, aA, aB, aLayer );
if( r )
{
wxString clearance = StringFromValue( r->GetUnits(), constraint.m_Value.Min(), true );
r->Report( wxString::Format( _( "Clearance: %s." ), clearance ) );
}
// JEY TODO: hook this up to new DRC engine to get "classic" sources as well; right now
// we're just reporting on rules....
aA->GetClearance( aLayer, aB, &source, r );
// JEY TODO: retire this version
// aA->GetClearance( aLayer, aB, &source, r );
}

View File

@ -110,6 +110,11 @@ private:
void onListNetsDialogClosed( wxCommandEvent& aEvent );
void onInspectClearanceDialogClosed( wxCommandEvent& aEvent );
void reportZoneConnection( ZONE_CONTAINER* aZone, D_PAD* aPad, REPORTER* r );
void reportCopperClearance( PCB_LAYER_ID aLayer, BOARD_CONNECTED_ITEM* aA, BOARD_ITEM* aB,
REPORTER* r );
private:
PCB_EDIT_FRAME* m_frame; // Pointer to the currently used edit frame.