diff --git a/pcbnew/dialogs/dialog_drc.cpp b/pcbnew/dialogs/dialog_drc.cpp index f4b5b0d7cc..bf75e6bbc6 100644 --- a/pcbnew/dialogs/dialog_drc.cpp +++ b/pcbnew/dialogs/dialog_drc.cpp @@ -606,7 +606,8 @@ void DIALOG_DRC::OnDRCItemRClick( wxDataViewEvent& aEvent ) || rcItem->GetErrorCode() == DRCE_ANNULAR_WIDTH || rcItem->GetErrorCode() == DRCE_DRILL_OUT_OF_RANGE || rcItem->GetErrorCode() == DRCE_MICROVIA_DRILL_OUT_OF_RANGE - || rcItem->GetErrorCode() == DRCE_CONNECTION_WIDTH ) + || rcItem->GetErrorCode() == DRCE_CONNECTION_WIDTH + || rcItem->GetErrorCode() == DRCE_ASSERTION_FAILURE ) { menu.Append( 3, _( "Run Inspect > Constraints Resolution" ) ); } diff --git a/pcbnew/dialogs/panel_setup_rules_help.md b/pcbnew/dialogs/panel_setup_rules_help.md index e1f4074345..69206e196c 100644 --- a/pcbnew/dialogs/panel_setup_rules_help.md +++ b/pcbnew/dialogs/panel_setup_rules_help.md @@ -176,8 +176,14 @@ matches items in the `/CLK_P` and `/CLK_N` nets. True if `A` and `B` are members of the same diff pair.

- A.memberOf('') -True if `A` is a member of the given group. Includes nested membership. + A.memberOfGroup('') +True if `A` is a member of the given group. The name can contain wildcards. +Includes nested membership. +

+ + A.memberOfFootprint('') +True if `A` is a member of a footprint matching the given reference designator. The +reference can contain wildcards.

A.existsOnLayer('') @@ -188,6 +194,10 @@ the canonical name (ie: `F.Cu`). NB: this returns true if `A` is on the given layer, independently of whether or not the rule is being evaluated for that layer. For the latter use a `(layer "layer_name")` clause in the rule. +

+ + !!! A.memberOf('') !!! +Deprecated; use `memberOfGroup()` instead.

!!! A.insideCourtyard('') !!! diff --git a/pcbnew/dialogs/panel_setup_rules_help_md.h b/pcbnew/dialogs/panel_setup_rules_help_md.h index abccac1285..5e60a639c2 100644 --- a/pcbnew/dialogs/panel_setup_rules_help_md.h +++ b/pcbnew/dialogs/panel_setup_rules_help_md.h @@ -177,8 +177,14 @@ _HKI( "### Top-level Clauses\n" "True if `A` and `B` are members of the same diff pair.\n" "

\n" "\n" -" A.memberOf('')\n" -"True if `A` is a member of the given group. Includes nested membership.\n" +" A.memberOfGroup('')\n" +"True if `A` is a member of the given group. The name can contain wildcards.\n" +"Includes nested membership.\n" +"

\n" +"\n" +" A.memberOfFootprint('')\n" +"True if `A` is a member of a footprint matching the given reference designator. The\n" +"reference can contain wildcards.\n" "

\n" "\n" " A.existsOnLayer('')\n" @@ -191,6 +197,10 @@ _HKI( "### Top-level Clauses\n" "For the latter use a `(layer \"layer_name\")` clause in the rule.\n" "

\n" "\n" +" !!! A.memberOf('') !!!\n" +"Deprecated; use `memberOfGroup()` instead.\n" +"

\n" +"\n" " !!! A.insideCourtyard('') !!!\n" "Deprecated; use `intersectsCourtyard()` instead.\n" "

\n" diff --git a/pcbnew/pcb_expr_functions.cpp b/pcbnew/pcb_expr_functions.cpp index 58c95308a5..3bb0ca09b7 100644 --- a/pcbnew/pcb_expr_functions.cpp +++ b/pcbnew/pcb_expr_functions.cpp @@ -755,7 +755,7 @@ static void enclosedByAreaFunc( LIBEVAL::CONTEXT* aCtx, void* self ) #define MISSING_GROUP_ARG( f ) \ wxString::Format( _( "Missing group name argument to %s." ), f ) -static void memberOfFunc( LIBEVAL::CONTEXT* aCtx, void* self ) +static void memberOfGroupFunc( LIBEVAL::CONTEXT* aCtx, void* self ) { LIBEVAL::VALUE* arg = aCtx->Pop(); LIBEVAL::VALUE* result = aCtx->AllocValue(); @@ -766,7 +766,7 @@ static void memberOfFunc( LIBEVAL::CONTEXT* aCtx, void* self ) if( !arg ) { if( aCtx->HasErrorCallback() ) - aCtx->ReportError( MISSING_GROUP_ARG( wxT( "memberOf()" ) ) ); + aCtx->ReportError( MISSING_GROUP_ARG( wxT( "memberOfGroup()" ) ) ); return; } @@ -798,6 +798,47 @@ static void memberOfFunc( LIBEVAL::CONTEXT* aCtx, void* self ) } +#define MISSING_REF_ARG( f ) \ + wxString::Format( _( "Missing footprint argument (reference designator) to %s." ), f ) + +static void memberOfFootprintFunc( LIBEVAL::CONTEXT* aCtx, void* self ) +{ + LIBEVAL::VALUE* arg = aCtx->Pop(); + LIBEVAL::VALUE* result = aCtx->AllocValue(); + + result->Set( 0.0 ); + aCtx->Push( result ); + + if( !arg ) + { + if( aCtx->HasErrorCallback() ) + aCtx->ReportError( MISSING_REF_ARG( wxT( "memberOfFootprint()" ) ) ); + + return; + } + + PCB_EXPR_VAR_REF* vref = static_cast( self ); + BOARD_ITEM* item = vref ? vref->GetObject( aCtx ) : nullptr; + + if( !item ) + return; + + result->SetDeferredEval( + [item, arg]() -> double + { + ; + + if( FOOTPRINT* parentFP = item->GetParentFootprint() ) + { + if( parentFP->GetReference().Matches( arg->AsString() ) ) + return 1.0; + } + + return 0.0; + } ); +} + + static void isMicroVia( LIBEVAL::CONTEXT* aCtx, void* self ) { PCB_EXPR_VAR_REF* vref = static_cast( self ); @@ -988,7 +1029,9 @@ void PCB_EXPR_BUILTIN_FUNCTIONS::RegisterAllFunctions() RegisterFunc( wxT( "isMicroVia()" ), isMicroVia ); RegisterFunc( wxT( "isBlindBuriedVia()" ), isBlindBuriedViaFunc ); - RegisterFunc( wxT( "memberOf('x')" ), memberOfFunc ); + RegisterFunc( wxT( "memberOf('x') DEPRECATED" ), memberOfGroupFunc ); + RegisterFunc( wxT( "memberOfGroup('x')" ), memberOfGroupFunc ); + RegisterFunc( wxT( "memberOfFootprint('x')" ), memberOfFootprintFunc ); RegisterFunc( wxT( "fromTo('x','y')" ), fromToFunc ); RegisterFunc( wxT( "isCoupledDiffPair()" ), isCoupledDiffPairFunc ); diff --git a/pcbnew/tools/board_inspection_tool.cpp b/pcbnew/tools/board_inspection_tool.cpp index bf5423f25a..f9765f129c 100644 --- a/pcbnew/tools/board_inspection_tool.cpp +++ b/pcbnew/tools/board_inspection_tool.cpp @@ -543,6 +543,16 @@ void BOARD_INSPECTION_TOOL::InspectDRCError( const std::shared_ptr& aDR break; + case DRCE_ASSERTION_FAILURE: + r = dialog->AddHTMLPage( _( "Assertions" ) ); + reportHeader( _( "Assertions for:" ), a, r ); + + if( compileError ) + reportCompileError( r ); + + drcEngine.ProcessAssertions( a, []( const DRC_CONSTRAINT* c ){}, r ); + break; + default: return; }