From dc60b80ae8d6d6070a0222c4410b993c2acd33a0 Mon Sep 17 00:00:00 2001 From: Seth Hillbrand Date: Fri, 12 Sep 2025 23:44:03 -0700 Subject: [PATCH] ADDED: API for injecting arbitrary DRC errors/warn Allows external tools to calculate/represent specialized DRC errors on the board Fixes https://gitlab.com/kicad/code/kicad/issues/21727 --- api/proto/board/board_commands.proto | 28 ++++++++++++++++ pcbnew/api/api_handler_pcb.cpp | 49 ++++++++++++++++++++++++++++ pcbnew/api/api_handler_pcb.h | 3 ++ pcbnew/api/api_pcb_enums.cpp | 29 ++++++++++++++++ qa/tests/api/test_api_enums.cpp | 6 ++++ 5 files changed, 115 insertions(+) diff --git a/api/proto/board/board_commands.proto b/api/proto/board/board_commands.proto index e5438182a1..b0828835b1 100644 --- a/api/proto/board/board_commands.proto +++ b/api/proto/board/board_commands.proto @@ -225,6 +225,34 @@ message PadstackPresenceResponse repeated PadstackPresenceEntry entries = 1; } +// DRC markers + +enum DrcSeverity +{ + DRS_UNKNOWN = 0; + DRS_WARNING = 1; + DRS_ERROR = 2; +} + +// Returns InjectDrcErrorResponse +message InjectDrcError +{ + kiapi.common.types.DocumentSpecifier board = 1; + + DrcSeverity severity = 2; + + string message = 3; + + kiapi.common.types.Vector2 position = 4; + + repeated kiapi.common.types.KIID items = 5; +} + +message InjectDrcErrorResponse +{ + kiapi.common.types.KIID marker = 1; +} + // PCB editor commands // returns BoardLayers diff --git a/pcbnew/api/api_handler_pcb.cpp b/pcbnew/api/api_handler_pcb.cpp index 34b2eef67e..cdb041213b 100644 --- a/pcbnew/api/api_handler_pcb.cpp +++ b/pcbnew/api/api_handler_pcb.cpp @@ -38,6 +38,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -46,6 +49,7 @@ #include #include +#include using namespace kiapi::common::commands; using types::CommandStatus; @@ -108,6 +112,8 @@ API_HANDLER_PCB::API_HANDLER_PCB( PCB_EDIT_FRAME* aFrame ) : &API_HANDLER_PCB::handleGetBoardEditorAppearanceSettings ); registerHandler( &API_HANDLER_PCB::handleSetBoardEditorAppearanceSettings ); + registerHandler( + &API_HANDLER_PCB::handleInjectDrcError ); } @@ -1581,3 +1587,46 @@ HANDLER_RESULT API_HANDLER_PCB::handleSetBoardEditorAppearanceSettings( return Empty(); } + + +HANDLER_RESULT API_HANDLER_PCB::handleInjectDrcError( + const HANDLER_CONTEXT& aCtx ) +{ + if( std::optional busy = checkForBusy() ) + return tl::unexpected( *busy ); + + HANDLER_RESULT documentValidation = validateDocument( aCtx.Request.board() ); + + if( !documentValidation ) + return tl::unexpected( documentValidation.error() ); + + SEVERITY severity = FromProtoEnum( aCtx.Request.severity() ); + int layer = severity == RPT_SEVERITY_WARNING ? LAYER_DRC_WARNING : LAYER_DRC_ERROR; + int code = severity == RPT_SEVERITY_WARNING ? DRCE_GENERIC_WARNING : DRCE_GENERIC_ERROR; + + std::shared_ptr drcItem = DRC_ITEM::Create( code ); + + drcItem->SetErrorMessage( wxString::FromUTF8( aCtx.Request.message() ) ); + + RC_ITEM::KIIDS ids; + + for( const auto& id : aCtx.Request.items() ) + ids.emplace_back( KIID( id.value() ) ); + + if( !ids.empty() ) + drcItem->SetItems( ids ); + + const auto& pos = aCtx.Request.position(); + VECTOR2I position( static_cast( pos.x_nm() ), static_cast( pos.y_nm() ) ); + + PCB_MARKER* marker = new PCB_MARKER( drcItem, position, layer ); + + COMMIT* commit = getCurrentCommit( aCtx.ClientName ); + commit->Add( marker ); + commit->Push( wxS( "API injected DRC marker" ) ); + + InjectDrcErrorResponse response; + response.mutable_marker()->set_value( marker->GetUUID().AsStdString() ); + + return response; +} diff --git a/pcbnew/api/api_handler_pcb.h b/pcbnew/api/api_handler_pcb.h index c08c3c1237..326fa3a049 100644 --- a/pcbnew/api/api_handler_pcb.h +++ b/pcbnew/api/api_handler_pcb.h @@ -145,6 +145,9 @@ private: HANDLER_RESULT handleSetBoardEditorAppearanceSettings( const HANDLER_CONTEXT& aCtx ); + HANDLER_RESULT handleInjectDrcError( + const HANDLER_CONTEXT& aCtx ); + protected: std::unique_ptr createCommit() override; diff --git a/pcbnew/api/api_pcb_enums.cpp b/pcbnew/api/api_pcb_enums.cpp index 3aeee0f302..9fbb90dc00 100644 --- a/pcbnew/api/api_pcb_enums.cpp +++ b/pcbnew/api/api_pcb_enums.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -35,6 +36,7 @@ // Adding something new here? Add it to test_api_enums.cpp! using namespace kiapi::board; +using namespace kiapi::board::commands; template<> types::PadType ToProtoEnum( PAD_ATTRIB aValue ) @@ -823,4 +825,31 @@ BOARD_STACKUP_ITEM_TYPE FromProtoEnum( BoardStackupLayerType aValue ) } } + +template<> +DrcSeverity ToProtoEnum( SEVERITY aValue ) +{ + switch( aValue ) + { + case RPT_SEVERITY_WARNING: return DrcSeverity::DRS_WARNING; + case RPT_SEVERITY_ERROR: return DrcSeverity::DRS_ERROR; + + default: + return DrcSeverity::DRS_UNKNOWN; + } +} + + +template<> +SEVERITY FromProtoEnum( DrcSeverity aValue ) +{ + switch( aValue ) + { + case DrcSeverity::DRS_WARNING: return RPT_SEVERITY_WARNING; + case DrcSeverity::DRS_ERROR: return RPT_SEVERITY_ERROR; + case DrcSeverity::DRS_UNKNOWN: + default: return RPT_SEVERITY_ERROR; + } +} + // Adding something new here? Add it to test_api_enums.cpp! diff --git a/qa/tests/api/test_api_enums.cpp b/qa/tests/api/test_api_enums.cpp index 7833e9cdda..c90b8f6b96 100644 --- a/qa/tests/api/test_api_enums.cpp +++ b/qa/tests/api/test_api_enums.cpp @@ -30,6 +30,7 @@ #include #include #include +#include // Board-specific #include @@ -267,4 +268,9 @@ BOOST_AUTO_TEST_CASE( BoardStackupLayerType ) testEnums(); } +BOOST_AUTO_TEST_CASE( DrcSeverity ) +{ + testEnums( true ); +} + BOOST_AUTO_TEST_SUITE_END()