mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-04-21 00:21:25 +00:00
Handle ERC/DRC assertions in drawing sheet.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/19132
This commit is contained in:
parent
55ca13e7cf
commit
4883c27972
common
eeschema/erc
include
pcbnew/drc
@ -56,7 +56,7 @@ enum Bracket
|
||||
};
|
||||
|
||||
|
||||
wxString ExpandTextVars( const wxString& aSource, const PROJECT* aProject )
|
||||
wxString ExpandTextVars( const wxString& aSource, const PROJECT* aProject, int aFlags )
|
||||
{
|
||||
std::function<bool( wxString* )> projectResolver =
|
||||
[&]( wxString* token ) -> bool
|
||||
@ -64,12 +64,12 @@ wxString ExpandTextVars( const wxString& aSource, const PROJECT* aProject )
|
||||
return aProject->TextVarResolver( token );
|
||||
};
|
||||
|
||||
return ExpandTextVars( aSource, &projectResolver );
|
||||
return ExpandTextVars( aSource, &projectResolver, aFlags );
|
||||
}
|
||||
|
||||
|
||||
wxString ExpandTextVars( const wxString& aSource,
|
||||
const std::function<bool( wxString* )>* aResolver )
|
||||
const std::function<bool( wxString* )>* aResolver, int aFlags )
|
||||
{
|
||||
static wxRegEx userDefinedWarningError( wxS( "^(ERC|DRC)_(WARNING|ERROR).*$" ) );
|
||||
wxString newbuf;
|
||||
@ -94,7 +94,7 @@ wxString ExpandTextVars( const wxString& aSource,
|
||||
if( token.IsEmpty() )
|
||||
continue;
|
||||
|
||||
if( userDefinedWarningError.Matches( token ) )
|
||||
if( ( aFlags & FOR_ERC_DRC ) == 0 && userDefinedWarningError.Matches( token ) )
|
||||
{
|
||||
// Only show user-defined warnings/errors during ERC/DRC
|
||||
}
|
||||
|
@ -173,7 +173,7 @@ wxString DS_DRAW_ITEM_LIST::BuildFullText( const wxString& aTextbase )
|
||||
}
|
||||
else if( m_titleBlock )
|
||||
{
|
||||
if( m_titleBlock->TextVarResolver( token, m_project ) )
|
||||
if( m_titleBlock->TextVarResolver( token, m_project, m_flags ) )
|
||||
{
|
||||
// No need for tokenUpdated; TITLE_BLOCK::TextVarResolver() already goes
|
||||
// up to the project.
|
||||
@ -185,7 +185,7 @@ wxString DS_DRAW_ITEM_LIST::BuildFullText( const wxString& aTextbase )
|
||||
|
||||
m_titleBlock = nullptr;
|
||||
{
|
||||
*token = ExpandTextVars( *token, &wsResolver );
|
||||
*token = ExpandTextVars( *token, &wsResolver, m_flags );
|
||||
}
|
||||
m_titleBlock = savedTitleBlock;
|
||||
|
||||
@ -200,7 +200,7 @@ wxString DS_DRAW_ITEM_LIST::BuildFullText( const wxString& aTextbase )
|
||||
|
||||
if( tokenUpdated )
|
||||
{
|
||||
*token = ExpandTextVars( *token, m_project );
|
||||
*token = ExpandTextVars( *token, m_project, m_flags );
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -210,7 +210,7 @@ wxString DS_DRAW_ITEM_LIST::BuildFullText( const wxString& aTextbase )
|
||||
return false;
|
||||
};
|
||||
|
||||
return ExpandTextVars( aTextbase, &wsResolver );
|
||||
return ExpandTextVars( aTextbase, &wsResolver, m_flags );
|
||||
}
|
||||
|
||||
|
||||
|
@ -92,7 +92,7 @@ void TITLE_BLOCK::GetContextualTextVars( wxArrayString* aVars )
|
||||
}
|
||||
|
||||
|
||||
bool TITLE_BLOCK::TextVarResolver( wxString* aToken, const PROJECT* aProject ) const
|
||||
bool TITLE_BLOCK::TextVarResolver( wxString* aToken, const PROJECT* aProject, int aFlags ) const
|
||||
{
|
||||
bool tokenUpdated = false;
|
||||
wxString originalToken = *aToken;
|
||||
@ -159,7 +159,7 @@ bool TITLE_BLOCK::TextVarResolver( wxString* aToken, const PROJECT* aProject ) c
|
||||
if( aToken->IsSameAs( wxT( "CURRENT_DATE" ) ) )
|
||||
*aToken = getCurrentDate();
|
||||
else if( aProject )
|
||||
*aToken = ExpandTextVars( *aToken, aProject );
|
||||
*aToken = ExpandTextVars( *aToken, aProject, aFlags );
|
||||
|
||||
// This is the default fallback, so don't claim we resolved it
|
||||
if( *aToken == wxT( "${" ) + originalToken + wxT( "}" ) )
|
||||
|
@ -182,7 +182,7 @@ int ERC_TESTER::TestDuplicateSheetNames( bool aCreateMarker )
|
||||
|
||||
void ERC_TESTER::TestTextVars( DS_PROXY_VIEW_ITEM* aDrawingSheet )
|
||||
{
|
||||
DS_DRAW_ITEM_LIST wsItems( schIUScale );
|
||||
DS_DRAW_ITEM_LIST wsItems( schIUScale, FOR_ERC_DRC );
|
||||
|
||||
auto unresolved =
|
||||
[this]( wxString str )
|
||||
@ -193,7 +193,7 @@ void ERC_TESTER::TestTextVars( DS_PROXY_VIEW_ITEM* aDrawingSheet )
|
||||
|
||||
auto testAssertion =
|
||||
[]( const SCH_ITEM* item, const SCH_SHEET_PATH& sheet, SCH_SCREEN* screen,
|
||||
const wxString& text )
|
||||
const wxString& text, const VECTOR2I& pos )
|
||||
{
|
||||
static wxRegEx warningExpr( wxS( "^\\$\\{ERC_WARNING\\s*([^}]*)\\}(.*)$" ) );
|
||||
static wxRegEx errorExpr( wxS( "^\\$\\{ERC_ERROR\\s*([^}]*)\\}(.*)$" ) );
|
||||
@ -201,26 +201,42 @@ void ERC_TESTER::TestTextVars( DS_PROXY_VIEW_ITEM* aDrawingSheet )
|
||||
if( warningExpr.Matches( text ) )
|
||||
{
|
||||
std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_GENERIC_WARNING );
|
||||
wxString ercText = warningExpr.GetMatch( text, 1 );
|
||||
|
||||
if( item )
|
||||
ercItem->SetItems( item );
|
||||
else
|
||||
ercText += _( " (in drawing sheet)" );
|
||||
|
||||
ercItem->SetItems( item );
|
||||
ercItem->SetSheetSpecificPath( sheet );
|
||||
ercItem->SetErrorMessage( warningExpr.GetMatch( text, 1 ) );
|
||||
ercItem->SetErrorMessage( ercText );
|
||||
|
||||
SCH_MARKER* marker = new SCH_MARKER( ercItem, item->GetPosition() );
|
||||
SCH_MARKER* marker = new SCH_MARKER( ercItem, pos );
|
||||
screen->Append( marker );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if( errorExpr.Matches( text ) )
|
||||
{
|
||||
std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_GENERIC_ERROR );
|
||||
wxString ercText = errorExpr.GetMatch( text, 1 );
|
||||
|
||||
if( item )
|
||||
ercItem->SetItems( item );
|
||||
else
|
||||
ercText += _( " (in drawing sheet)" );
|
||||
|
||||
ercItem->SetItems( item );
|
||||
ercItem->SetSheetSpecificPath( sheet );
|
||||
ercItem->SetErrorMessage( errorExpr.GetMatch( text, 1 ) );
|
||||
ercItem->SetErrorMessage( ercText );
|
||||
|
||||
SCH_MARKER* marker = new SCH_MARKER( ercItem, item->GetPosition() );
|
||||
SCH_MARKER* marker = new SCH_MARKER( ercItem, pos );
|
||||
screen->Append( marker );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
if( aDrawingSheet )
|
||||
@ -256,7 +272,7 @@ void ERC_TESTER::TestTextVars( DS_PROXY_VIEW_ITEM* aDrawingSheet )
|
||||
screen->Append( marker );
|
||||
}
|
||||
|
||||
testAssertion( &field, sheet, screen, field.GetText() );
|
||||
testAssertion( &field, sheet, screen, field.GetText(), field.GetPosition() );
|
||||
}
|
||||
|
||||
symbol->GetLibSymbolRef()->RunOnChildren(
|
||||
@ -284,7 +300,8 @@ void ERC_TESTER::TestTextVars( DS_PROXY_VIEW_ITEM* aDrawingSheet )
|
||||
screen->Append( marker );
|
||||
}
|
||||
|
||||
testAssertion( symbol, sheet, screen, textItem->GetText() );
|
||||
testAssertion( symbol, sheet, screen, textItem->GetText(),
|
||||
textItem->GetPosition() );
|
||||
}
|
||||
else if( child->Type() == SCH_TEXTBOX_T )
|
||||
{
|
||||
@ -304,7 +321,8 @@ void ERC_TESTER::TestTextVars( DS_PROXY_VIEW_ITEM* aDrawingSheet )
|
||||
screen->Append( marker );
|
||||
}
|
||||
|
||||
testAssertion( symbol, sheet, screen, textboxItem->GetText() );
|
||||
testAssertion( symbol, sheet, screen, textboxItem->GetText(),
|
||||
textboxItem->GetPosition() );
|
||||
}
|
||||
} );
|
||||
}
|
||||
@ -322,7 +340,7 @@ void ERC_TESTER::TestTextVars( DS_PROXY_VIEW_ITEM* aDrawingSheet )
|
||||
screen->Append( marker );
|
||||
}
|
||||
|
||||
testAssertion( &field, sheet, screen, field.GetText() );
|
||||
testAssertion( &field, sheet, screen, field.GetText(), field.GetPosition() );
|
||||
}
|
||||
}
|
||||
else if( item->Type() == SCH_SHEET_T )
|
||||
@ -341,7 +359,7 @@ void ERC_TESTER::TestTextVars( DS_PROXY_VIEW_ITEM* aDrawingSheet )
|
||||
screen->Append( marker );
|
||||
}
|
||||
|
||||
testAssertion( &field, sheet, screen, field.GetText() );
|
||||
testAssertion( &field, sheet, screen, field.GetText(), field.GetPosition() );
|
||||
}
|
||||
|
||||
SCH_SHEET_PATH subSheetPath = sheet;
|
||||
@ -372,7 +390,7 @@ void ERC_TESTER::TestTextVars( DS_PROXY_VIEW_ITEM* aDrawingSheet )
|
||||
screen->Append( marker );
|
||||
}
|
||||
|
||||
testAssertion( text, sheet, screen, text->GetText() );
|
||||
testAssertion( text, sheet, screen, text->GetText(), text->GetPosition() );
|
||||
}
|
||||
else if( SCH_TEXTBOX* textBox = dynamic_cast<SCH_TEXTBOX*>( item ) )
|
||||
{
|
||||
@ -386,7 +404,7 @@ void ERC_TESTER::TestTextVars( DS_PROXY_VIEW_ITEM* aDrawingSheet )
|
||||
screen->Append( marker );
|
||||
}
|
||||
|
||||
testAssertion( textBox, sheet, screen, textBox->GetText() );
|
||||
testAssertion( textBox, sheet, screen, textBox->GetText(), textBox->GetPosition() );
|
||||
}
|
||||
}
|
||||
|
||||
@ -394,7 +412,11 @@ void ERC_TESTER::TestTextVars( DS_PROXY_VIEW_ITEM* aDrawingSheet )
|
||||
{
|
||||
if( DS_DRAW_ITEM_TEXT* text = dynamic_cast<DS_DRAW_ITEM_TEXT*>( item ) )
|
||||
{
|
||||
if( text->GetShownText( true ).Matches( wxS( "*${*}*" ) ) )
|
||||
if( testAssertion( nullptr, sheet, screen, text->GetText(), text->GetPosition() ) )
|
||||
{
|
||||
// Don't run unresolved test
|
||||
}
|
||||
else if( text->GetShownText( true ).Matches( wxS( "*${*}*" ) ) )
|
||||
{
|
||||
std::shared_ptr<ERC_ITEM> erc = ERC_ITEM::Create( ERCE_UNRESOLVED_VARIABLE );
|
||||
erc->SetErrorMessage( _( "Unresolved text variable in drawing sheet" ) );
|
||||
|
@ -88,10 +88,14 @@ KICOMMON_API const wxString ExpandEnvVarSubstitutions( const wxString& aString,
|
||||
/**
|
||||
* Expand '${var-name}' templates in text.
|
||||
*/
|
||||
KICOMMON_API wxString ExpandTextVars( const wxString& aSource,
|
||||
const std::function<bool( wxString* )>* aResolver );
|
||||
#define FOR_ERC_DRC 1
|
||||
|
||||
KICOMMON_API wxString ExpandTextVars( const wxString& aSource, const PROJECT* aProject );
|
||||
KICOMMON_API wxString ExpandTextVars( const wxString& aSource,
|
||||
const std::function<bool( wxString* )>* aResolver,
|
||||
int aFlags = 0 );
|
||||
|
||||
KICOMMON_API wxString ExpandTextVars( const wxString& aSource, const PROJECT* aProject,
|
||||
int aFlags = 0 );
|
||||
|
||||
/**
|
||||
* Returns any variables unexpanded, e.g. ${VAR} -> VAR
|
||||
|
@ -400,7 +400,7 @@ private:
|
||||
class DS_DRAW_ITEM_LIST
|
||||
{
|
||||
public:
|
||||
DS_DRAW_ITEM_LIST( const EDA_IU_SCALE& aIuScale ) :
|
||||
DS_DRAW_ITEM_LIST( const EDA_IU_SCALE& aIuScale, int aFlags = 0 ) :
|
||||
m_iuScale( aIuScale )
|
||||
{
|
||||
m_idx = 0;
|
||||
@ -411,6 +411,7 @@ public:
|
||||
m_titleBlock = nullptr;
|
||||
m_project = nullptr;
|
||||
m_isFirstPage = true;
|
||||
m_flags = aFlags;
|
||||
m_properties = nullptr;
|
||||
}
|
||||
|
||||
@ -578,6 +579,7 @@ protected:
|
||||
wxString m_pageNumber; ///< The actual page number displayed in the title block.
|
||||
wxString m_sheetLayer; // for text variable references
|
||||
const PROJECT* m_project; // for project-based text variable references
|
||||
int m_flags;
|
||||
|
||||
const std::map<wxString, wxString>* m_properties; // for text variable references
|
||||
};
|
||||
|
@ -116,7 +116,7 @@ public:
|
||||
}
|
||||
|
||||
static void GetContextualTextVars( wxArrayString* aVars );
|
||||
bool TextVarResolver( wxString* aToken, const PROJECT* aProject ) const;
|
||||
bool TextVarResolver( wxString* aToken, const PROJECT* aProject, int aFlags = 0 ) const;
|
||||
|
||||
/**
|
||||
* Output the object to \a aFormatter in s-expression form.
|
||||
|
@ -280,44 +280,6 @@ void DRC_TEST_PROVIDER_MISC::testAssertions()
|
||||
} );
|
||||
}
|
||||
|
||||
if( !m_drcEngine->IsErrorLimitExceeded( DRCE_GENERIC_WARNING ) )
|
||||
{
|
||||
if( EDA_TEXT* textItem = dynamic_cast<EDA_TEXT*>( item ) )
|
||||
{
|
||||
static wxRegEx warningExpr( wxS( "^\\$\\{DRC_WARNING\\s*([^}]*)\\}(.*)$" ) );
|
||||
|
||||
wxString text = textItem->GetText();
|
||||
|
||||
if( warningExpr.Matches( text ) )
|
||||
{
|
||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_GENERIC_WARNING );
|
||||
drcItem->SetItems( item );
|
||||
drcItem->SetErrorMessage( warningExpr.GetMatch( text, 1 ) );
|
||||
|
||||
reportViolation( drcItem, item->GetPosition(), item->GetLayer() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !m_drcEngine->IsErrorLimitExceeded( DRCE_GENERIC_ERROR ) )
|
||||
{
|
||||
if( EDA_TEXT* textItem = dynamic_cast<EDA_TEXT*>( item ) )
|
||||
{
|
||||
static wxRegEx errorExpr( wxS( "^\\$\\{DRC_ERROR\\s*([^}]*)\\}(.*)$" ) );
|
||||
|
||||
wxString text = textItem->GetText();
|
||||
|
||||
if( errorExpr.Matches( text ) )
|
||||
{
|
||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_GENERIC_ERROR );
|
||||
drcItem->SetItems( item );
|
||||
drcItem->SetErrorMessage( errorExpr.GetMatch( text, 1 ) );
|
||||
|
||||
reportViolation( drcItem, item->GetPosition(), item->GetLayer() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
@ -339,6 +301,55 @@ void DRC_TEST_PROVIDER_MISC::testTextVars()
|
||||
PCB_DIMENSION_T
|
||||
};
|
||||
|
||||
auto testAssertion =
|
||||
[&]( BOARD_ITEM* item, const wxString& text, const VECTOR2I& pos, int layer )
|
||||
{
|
||||
static wxRegEx warningExpr( wxS( "^\\$\\{DRC_WARNING\\s*([^}]*)\\}(.*)$" ) );
|
||||
static wxRegEx errorExpr( wxS( "^\\$\\{DRC_ERROR\\s*([^}]*)\\}(.*)$" ) );
|
||||
|
||||
if( warningExpr.Matches( text ) )
|
||||
{
|
||||
if( !m_drcEngine->IsErrorLimitExceeded( DRCE_GENERIC_WARNING ) )
|
||||
{
|
||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_GENERIC_WARNING );
|
||||
wxString drcText = warningExpr.GetMatch( text, 1 );
|
||||
|
||||
if( item )
|
||||
drcItem->SetItems( item );
|
||||
else
|
||||
drcText += _( " (in drawing sheet)" );
|
||||
|
||||
drcItem->SetErrorMessage( drcText );
|
||||
|
||||
reportViolation( drcItem, pos, layer );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if( errorExpr.Matches( text ) )
|
||||
{
|
||||
if( !m_drcEngine->IsErrorLimitExceeded( DRCE_GENERIC_ERROR ) )
|
||||
{
|
||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_GENERIC_ERROR );
|
||||
wxString drcText = errorExpr.GetMatch( text, 1 );
|
||||
|
||||
if( item )
|
||||
drcItem->SetItems( item );
|
||||
else
|
||||
drcText += _( " (in drawing sheet)" );
|
||||
|
||||
drcItem->SetErrorMessage( drcText );
|
||||
|
||||
reportViolation( drcItem, pos, layer );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
forEachGeometryItem( itemTypes, LSET::AllLayersMask(),
|
||||
[&]( BOARD_ITEM* item ) -> bool
|
||||
{
|
||||
@ -367,13 +378,15 @@ void DRC_TEST_PROVIDER_MISC::testTextVars()
|
||||
|
||||
reportViolation( drcItem, item->GetPosition(), item->GetLayer() );
|
||||
}
|
||||
|
||||
testAssertion( item, textItem->GetText(), item->GetPosition(), item->GetLayer() );
|
||||
}
|
||||
|
||||
return true;
|
||||
} );
|
||||
|
||||
DS_PROXY_VIEW_ITEM* drawingSheet = m_drcEngine->GetDrawingSheet();
|
||||
DS_DRAW_ITEM_LIST drawItems( pcbIUScale );
|
||||
DS_DRAW_ITEM_LIST drawItems( pcbIUScale, FOR_ERC_DRC );
|
||||
|
||||
if( !drawingSheet || m_drcEngine->IsErrorLimitExceeded( DRCE_UNRESOLVED_VARIABLE ) )
|
||||
return;
|
||||
@ -394,14 +407,19 @@ void DRC_TEST_PROVIDER_MISC::testTextVars()
|
||||
if( m_drcEngine->IsCancelled() )
|
||||
return;
|
||||
|
||||
DS_DRAW_ITEM_TEXT* text = dynamic_cast<DS_DRAW_ITEM_TEXT*>( item );
|
||||
|
||||
if( text && text->GetShownText( true ).Matches( wxT( "*${*}*" ) ) )
|
||||
if( DS_DRAW_ITEM_TEXT* text = dynamic_cast<DS_DRAW_ITEM_TEXT*>( item ) )
|
||||
{
|
||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_UNRESOLVED_VARIABLE );
|
||||
drcItem->SetItems( drawingSheet );
|
||||
if( testAssertion( nullptr, text->GetText(), text->GetPosition(), LAYER_DRAWINGSHEET ) )
|
||||
{
|
||||
// Don't run unresolved test
|
||||
}
|
||||
else if( text->GetShownText( true ).Matches( wxT( "*${*}*" ) ) )
|
||||
{
|
||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_UNRESOLVED_VARIABLE );
|
||||
drcItem->SetItems( drawingSheet );
|
||||
|
||||
reportViolation( drcItem, text->GetPosition(), LAYER_DRAWINGSHEET );
|
||||
reportViolation( drcItem, text->GetPosition(), LAYER_DRAWINGSHEET );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user