diff --git a/common/notifications_manager.cpp b/common/notifications_manager.cpp index 647c9e5b1b..235477cc11 100644 --- a/common/notifications_manager.cpp +++ b/common/notifications_manager.cpp @@ -266,7 +266,7 @@ void NOTIFICATIONS_MANAGER::Load() { nlohmann::json saved_json; - std::ifstream saved_json_stream( m_destFileName.GetFullPath().ToUTF8() ); + std::ifstream saved_json_stream( m_destFileName.GetFullPath().fn_str() ); try { @@ -289,7 +289,7 @@ void NOTIFICATIONS_MANAGER::Load() void NOTIFICATIONS_MANAGER::Save() { - std::ofstream jsonFileStream( m_destFileName.GetFullPath().ToUTF8() ); + std::ofstream jsonFileStream( m_destFileName.GetFullPath().fn_str() ); nlohmann::json saveJson = nlohmann::json( m_notifications ); jsonFileStream << std::setw( 4 ) << saveJson << std::endl; diff --git a/common/rc_item.cpp b/common/rc_item.cpp index acce081d4f..2b54b91f34 100644 --- a/common/rc_item.cpp +++ b/common/rc_item.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -76,22 +77,30 @@ void RC_ITEM::SetItems( const EDA_ITEM* aItem, const EDA_ITEM* bItem, } -wxString RC_ITEM::ShowReport( UNITS_PROVIDER* aUnitsProvider, SEVERITY aSeverity, - const std::map& aItemMap ) const +wxString getSeverityString( SEVERITY aSeverity ) { wxString severity; switch( aSeverity ) { - case RPT_SEVERITY_ERROR: severity = wxT( "Severity: error" ); break; - case RPT_SEVERITY_WARNING: severity = wxT( "Severity: warning" ); break; - case RPT_SEVERITY_ACTION: severity = wxT( "Severity: action" ); break; - case RPT_SEVERITY_INFO: severity = wxT( "Severity: info" ); break; - case RPT_SEVERITY_EXCLUSION: severity = wxT( "Severity: exclusion" ); break; - case RPT_SEVERITY_DEBUG: severity = wxT( "Severity: debug" ); break; - default: ; + case RPT_SEVERITY_ERROR: severity = wxS( "error" ); break; + case RPT_SEVERITY_WARNING: severity = wxS( "warning" ); break; + case RPT_SEVERITY_ACTION: severity = wxS( "action" ); break; + case RPT_SEVERITY_INFO: severity = wxS( "info" ); break; + case RPT_SEVERITY_EXCLUSION: severity = wxS( "exclusion" ); break; + case RPT_SEVERITY_DEBUG: severity = wxS( "debug" ); break; + default:; }; + return severity; +} + + +wxString RC_ITEM::ShowReport( UNITS_PROVIDER* aUnitsProvider, SEVERITY aSeverity, + const std::map& aItemMap ) const +{ + wxString severity = getSeverityString( aSeverity ); + if( m_parent && m_parent->IsExcluded() ) severity += wxT( " (excluded)" ); @@ -146,6 +155,59 @@ wxString RC_ITEM::ShowReport( UNITS_PROVIDER* aUnitsProvider, SEVERITY aSeverity } +void RC_ITEM::GetJsonViolation( RC_JSON::VIOLATION& aViolation, UNITS_PROVIDER* aUnitsProvider, + SEVERITY aSeverity, + const std::map& aItemMap ) const +{ + wxString severity = getSeverityString( aSeverity ); + + aViolation.severity = severity; + aViolation.description = GetViolatingRuleDesc(); + aViolation.type = GetSettingsKey(); + + EDA_ITEM* mainItem = nullptr; + EDA_ITEM* auxItem = nullptr; + + auto ii = aItemMap.find( GetMainItemID() ); + + if( ii != aItemMap.end() ) + mainItem = ii->second; + + ii = aItemMap.find( GetAuxItemID() ); + + if( ii != aItemMap.end() ) + auxItem = ii->second; + + if( mainItem ) + { + RC_JSON::AFFECTED_ITEM item; + item.description = mainItem->GetItemDescription( aUnitsProvider ); + item.uuid = mainItem->m_Uuid.AsString(); + item.pos.x = EDA_UNIT_UTILS::UI::ToUserUnit( aUnitsProvider->GetIuScale(), + aUnitsProvider->GetUserUnits(), + mainItem->GetPosition().x ); + item.pos.y = EDA_UNIT_UTILS::UI::ToUserUnit( aUnitsProvider->GetIuScale(), + aUnitsProvider->GetUserUnits(), + mainItem->GetPosition().y ); + aViolation.items.emplace_back( item ); + } + + if( auxItem ) + { + RC_JSON::AFFECTED_ITEM item; + item.description = auxItem->GetItemDescription( aUnitsProvider ); + item.uuid = auxItem->m_Uuid.AsString(); + item.pos.x = EDA_UNIT_UTILS::UI::ToUserUnit( aUnitsProvider->GetIuScale(), + aUnitsProvider->GetUserUnits(), + auxItem->GetPosition().x ); + item.pos.y = EDA_UNIT_UTILS::UI::ToUserUnit( aUnitsProvider->GetIuScale(), + aUnitsProvider->GetUserUnits(), + auxItem->GetPosition().y ); + aViolation.items.emplace_back( item ); + } +} + + KIID RC_TREE_MODEL::ToUUID( wxDataViewItem aItem ) { const RC_TREE_NODE* node = RC_TREE_MODEL::ToNode( aItem ); diff --git a/common/wildcards_and_files_ext.cpp b/common/wildcards_and_files_ext.cpp index bb1428b647..670e087076 100644 --- a/common/wildcards_and_files_ext.cpp +++ b/common/wildcards_and_files_ext.cpp @@ -190,6 +190,7 @@ const std::string TextFileExtension( "txt" ); const std::string MarkdownFileExtension( "md" ); const std::string CsvFileExtension( "csv" ); const std::string XmlFileExtension( "xml" ); +const std::string JsonFileExtension( "json" ); const wxString GerberFileExtensionsRegex( "(gbr|gko|pho|(g[tb][alops])|(gm?\\d\\d*)|(gp[tb]))" ); diff --git a/include/rc_item.h b/include/rc_item.h index 4cc53c2e1c..f5ad57720d 100644 --- a/include/rc_item.h +++ b/include/rc_item.h @@ -36,6 +36,10 @@ class RC_ITEM; class EDA_ITEM; class EDA_DRAW_FRAME; +namespace RC_JSON +{ +struct VIOLATION; +} /** * Provide an abstract interface of a RC_ITEM* list manager. @@ -133,6 +137,19 @@ public: virtual wxString ShowReport( UNITS_PROVIDER* aUnitsProvider, SEVERITY aSeverity, const std::map& aItemMap ) const; + /** + * Translate this object into an RC_JSON::VIOLATION object + * + * @param aViolation is the violation to be populated by info from this item + * @param aUnitsProvider is the units provider that will be used to output coordinates + * @param aSeverity is the severity of this item + * @param aItemMap is a map allowing the lookup of items from KIIDs + * + * @return None + */ + virtual void GetJsonViolation( RC_JSON::VIOLATION& aViolation, UNITS_PROVIDER* aUnitsProvider, + SEVERITY aSeverity, const std::map& aItemMap ) const; + int GetErrorCode() const { return m_errorCode; } void SetErrorCode( int aCode ) { m_errorCode = aCode; } @@ -272,8 +289,9 @@ public: void DeleteItems( bool aCurrentOnly, bool aIncludeExclusions, bool aDeep ); protected: - void rebuildModel( std::shared_ptr aProvider, int aSeverities ); - void onSizeView( wxSizeEvent& aEvent ); + void rebuildModel( std::shared_ptr aProvider, int aSeverities ); + void onSizeView( wxSizeEvent& aEvent ); + wxString getSeverityString( SEVERITY aSeverity ); EDA_DRAW_FRAME* m_editFrame; wxDataViewCtrl* m_view; diff --git a/include/rc_json_schema.h b/include/rc_json_schema.h new file mode 100644 index 0000000000..7f53020fba --- /dev/null +++ b/include/rc_json_schema.h @@ -0,0 +1,103 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#ifndef RC_JSON_SCHEMA_H +#define RC_JSON_SCHEMA_H + +#include +#include +#include + +/** + * Contains the json serialization structs for DRC and ERC reports + * If you are trying to change the output schema + * Please update the schemas located in /resources/schemas/ as both documentation + * and use by end user implementations + */ +namespace RC_JSON +{ +struct COORDINATE +{ + double x; + double y; +}; +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE( COORDINATE, x, y ) + +struct AFFECTED_ITEM +{ + wxString uuid; + wxString description; + COORDINATE pos; +}; + +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE( AFFECTED_ITEM, uuid, description, pos ) + +struct VIOLATION +{ + wxString type; + wxString description; + wxString severity; + std::vector items; +}; + +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE( VIOLATION, type, description, severity, items ) + +struct REPORT_BASE +{ + wxString source; + wxString date; + wxString kicad_version; + wxString type; + wxString coordinate_units; +}; + +struct DRC_REPORT : REPORT_BASE +{ + DRC_REPORT() { type = wxS( "drc" ); } + + std::vector violations; + std::vector unconnected_items; + std::vector schematic_parity; +}; + +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE( DRC_REPORT, source, date, kicad_version, violations, + unconnected_items, schematic_parity, coordinate_units ) + +struct ERC_SHEET +{ + wxString uuid; + wxString path; + std::vector violations; +}; + +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE( ERC_SHEET, uuid, path, violations ) + +struct ERC_REPORT : REPORT_BASE +{ + ERC_REPORT() { type = wxS( "erc" ); } + + std::vector sheets; +}; + +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE( ERC_REPORT, source, date, kicad_version, sheets, + coordinate_units ) + +} // namespace RC_JSON + +#endif \ No newline at end of file diff --git a/include/wildcards_and_files_ext.h b/include/wildcards_and_files_ext.h index 645f095d5f..7052034341 100644 --- a/include/wildcards_and_files_ext.h +++ b/include/wildcards_and_files_ext.h @@ -176,6 +176,7 @@ extern const std::string TextFileExtension; extern const std::string MarkdownFileExtension; extern const std::string CsvFileExtension; extern const std::string XmlFileExtension; +extern const std::string JsonFileExtension; extern const wxString GerberFileExtensionsRegex; diff --git a/kicad/cli/command_pcb_drc.cpp b/kicad/cli/command_pcb_drc.cpp index f894ba76c4..ac73f214fb 100644 --- a/kicad/cli/command_pcb_drc.cpp +++ b/kicad/cli/command_pcb_drc.cpp @@ -41,7 +41,7 @@ CLI::PCB_DRC_COMMAND::PCB_DRC_COMMAND() : EXPORT_PCB_BASE_COMMAND( "drc" ) { m_argParser.add_argument( ARG_FORMAT ) .default_value( std::string( "report" ) ) - .help( UTF8STDSTR( _( "Output file format, options: report" ) ) ); + .help( UTF8STDSTR( _( "Output file format, options: json, report" ) ) ); m_argParser.add_argument( ARG_ALL_TRACK_ERRORS ) .help( UTF8STDSTR( _( "Report all errors for each track" ) ) ) @@ -140,6 +140,10 @@ int CLI::PCB_DRC_COMMAND::doPerform( KIWAY& aKiway ) { drcJob->m_format = JOB_PCB_DRC::OUTPUT_FORMAT::REPORT; } + else if( format == "json" ) + { + drcJob->m_format = JOB_PCB_DRC::OUTPUT_FORMAT::JSON; + } else { wxFprintf( stderr, _( "Invalid report format\n" ) ); diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt index 51ce9d2e01..136f50c1be 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -233,6 +233,7 @@ set( PCBNEW_MICROWAVE_SRCS set( PCBNEW_DRC_SRCS drc/drc_interactive_courtyard_clearance.cpp + drc/drc_report.cpp drc/drc_test_provider.cpp drc/drc_test_provider_annular_width.cpp drc/drc_test_provider_disallow.cpp diff --git a/pcbnew/dialogs/dialog_drc.cpp b/pcbnew/dialogs/dialog_drc.cpp index 137847c81f..2df69fa599 100644 --- a/pcbnew/dialogs/dialog_drc.cpp +++ b/pcbnew/dialogs/dialog_drc.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -869,7 +870,10 @@ void DIALOG_DRC::OnSaveReport( wxCommandEvent& aEvent ) fn.MakeAbsolute( prj_path ); } - if( DRC_TOOL::WriteReport( fn.GetFullPath(), m_frame->GetBoard(), GetUserUnits(), m_markersProvider, m_ratsnestProvider, m_fpWarningsProvider ) ) + DRC_REPORT reportWriter( m_frame->GetBoard(), GetUserUnits(), m_markersProvider, + m_ratsnestProvider, m_fpWarningsProvider ); + + if( reportWriter.WriteJsonReport( fn.GetFullPath() ) ) { m_messages->Report( wxString::Format( _( "Report file '%s' created
" ), fn.GetFullPath() ) ); diff --git a/pcbnew/drc/drc_report.cpp b/pcbnew/drc/drc_report.cpp new file mode 100644 index 0000000000..66de6a4b49 --- /dev/null +++ b/pcbnew/drc/drc_report.cpp @@ -0,0 +1,172 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include + +#include +#include +#include +#include "drc_report.h" +#include +#include +#include +#include +#include + + +DRC_REPORT::DRC_REPORT(BOARD* aBoard, EDA_UNITS aReportUnits, + std::shared_ptr aMarkersProvider, + std::shared_ptr aRatsnestProvider, + std::shared_ptr aFpWarningsProvider) : + m_board( aBoard ), + m_reportUnits( aReportUnits ), + m_markersProvider( aMarkersProvider ), + m_ratsnestProvider( aRatsnestProvider ), + m_fpWarningsProvider( aFpWarningsProvider ) +{ + +} + + +bool DRC_REPORT::WriteTextReport( const wxString& aFullFileName ) +{ + FILE* fp = wxFopen( aFullFileName, wxT( "w" ) ); + + if( fp == nullptr ) + return false; + + std::map itemMap; + m_board->FillItemMap( itemMap ); + + UNITS_PROVIDER unitsProvider( pcbIUScale, m_reportUnits ); + BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings(); + int count; + + fprintf( fp, "** Drc report for %s **\n", TO_UTF8( m_board->GetFileName() ) ); + + fprintf( fp, "** Created on %s **\n", TO_UTF8( GetISO8601CurrentDateTime() ) ); + + count = m_markersProvider->GetCount(); + + fprintf( fp, "\n** Found %d DRC violations **\n", count ); + + for( int i = 0; i < count; ++i ) + { + const std::shared_ptr& item = m_markersProvider->GetItem( i ); + SEVERITY severity = item->GetParent()->GetSeverity(); + + if( severity == RPT_SEVERITY_EXCLUSION ) + severity = bds.GetSeverity( item->GetErrorCode() ); + + fprintf( fp, "%s", TO_UTF8( item->ShowReport( &unitsProvider, severity, itemMap ) ) ); + } + + count = m_ratsnestProvider->GetCount(); + + fprintf( fp, "\n** Found %d unconnected pads **\n", count ); + + for( int i = 0; i < count; ++i ) + { + const std::shared_ptr& item = m_ratsnestProvider->GetItem( i ); + SEVERITY severity = bds.GetSeverity( item->GetErrorCode() ); + + fprintf( fp, "%s", TO_UTF8( item->ShowReport( &unitsProvider, severity, itemMap ) ) ); + } + + count = m_fpWarningsProvider->GetCount(); + + fprintf( fp, "\n** Found %d Footprint errors **\n", count ); + + for( int i = 0; i < count; ++i ) + { + const std::shared_ptr& item = m_fpWarningsProvider->GetItem( i ); + SEVERITY severity = bds.GetSeverity( item->GetErrorCode() ); + + fprintf( fp, "%s", TO_UTF8( item->ShowReport( &unitsProvider, severity, itemMap ) ) ); + } + + + fprintf( fp, "\n** End of Report **\n" ); + + fclose( fp ); + + return true; +} + + +bool DRC_REPORT::WriteJsonReport( const wxString& aFullFileName ) +{ + std::ofstream jsonFileStream( aFullFileName.fn_str() ); + + UNITS_PROVIDER unitsProvider( pcbIUScale, m_reportUnits ); + BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings(); + std::map itemMap; + m_board->FillItemMap( itemMap ); + + RC_JSON::DRC_REPORT reportHead; + reportHead.source = m_board->GetFileName(); + reportHead.date = GetISO8601CurrentDateTime(); + reportHead.kicad_version = GetMajorMinorPatchVersion(); + reportHead.coordinate_units = EDA_UNIT_UTILS::GetLabel( m_reportUnits ); + + for( int i = 0; i < m_markersProvider->GetCount(); ++i ) + { + const std::shared_ptr& item = m_markersProvider->GetItem( i ); + SEVERITY severity = item->GetParent()->GetSeverity(); + + if( severity == RPT_SEVERITY_EXCLUSION ) + severity = bds.GetSeverity( item->GetErrorCode() ); + + RC_JSON::VIOLATION violation; + item->GetJsonViolation( violation, &unitsProvider, severity, itemMap ); + + reportHead.violations.push_back( violation ); + } + + for( int i = 0; i < m_ratsnestProvider->GetCount(); ++i ) + { + const std::shared_ptr& item = m_ratsnestProvider->GetItem( i ); + SEVERITY severity = bds.GetSeverity( item->GetErrorCode() ); + + RC_JSON::VIOLATION violation; + item->GetJsonViolation( violation, &unitsProvider, severity, itemMap ); + + reportHead.unconnected_items.push_back( violation ); + } + + + for( int i = 0; i < m_fpWarningsProvider->GetCount(); ++i ) + { + const std::shared_ptr& item = m_ratsnestProvider->GetItem( i ); + SEVERITY severity = bds.GetSeverity( item->GetErrorCode() ); + + RC_JSON::VIOLATION violation; + item->GetJsonViolation( violation, &unitsProvider, severity, itemMap ); + + reportHead.schematic_parity.push_back( violation ); + } + + + nlohmann::json saveJson = nlohmann::json( reportHead ); + jsonFileStream << std::setw( 4 ) << saveJson << std::endl; + jsonFileStream.flush(); + jsonFileStream.close(); + + return true; +} \ No newline at end of file diff --git a/pcbnew/drc/drc_report.h b/pcbnew/drc/drc_report.h new file mode 100644 index 0000000000..7c6b827e5e --- /dev/null +++ b/pcbnew/drc/drc_report.h @@ -0,0 +1,51 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#ifndef DRC_REPORT_H +#define DRC_REPORT_H + +#include +#include +#include + +class BOARD; +class RC_ITEMS_PROVIDER; + +class DRC_REPORT +{ +public: + DRC_REPORT( BOARD* aBoard, + EDA_UNITS aReportUnits, + std::shared_ptr aMarkersProvider, + std::shared_ptr aRatsnestProvider, + std::shared_ptr aFpWarningsProvider ); + + bool WriteTextReport( const wxString& aFullFileName ); + bool WriteJsonReport( const wxString& aFullFileName ); + +private: + BOARD* m_board; + EDA_UNITS m_reportUnits; + std::shared_ptr m_markersProvider; + std::shared_ptr m_ratsnestProvider; + std::shared_ptr m_fpWarningsProvider; +}; + + +#endif \ No newline at end of file diff --git a/pcbnew/pcbnew_jobs_handler.cpp b/pcbnew/pcbnew_jobs_handler.cpp index 004df3684c..231fc29098 100644 --- a/pcbnew/pcbnew_jobs_handler.cpp +++ b/pcbnew/pcbnew_jobs_handler.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -866,7 +867,11 @@ int PCBNEW_JOBS_HANDLER::JobExportDrc( JOB* aJob ) { wxFileName fn = brd->GetFileName(); fn.SetName( fn.GetName() ); - fn.SetExt( ReportFileExtension ); + + if( drcJob->m_format == JOB_PCB_DRC::OUTPUT_FORMAT::JSON ) + fn.SetExt( JsonFileExtension ); + else + fn.SetExt( ReportFileExtension ); drcJob->m_outputFile = fn.GetFullName(); } @@ -922,8 +927,23 @@ int PCBNEW_JOBS_HANDLER::JobExportDrc( JOB* aJob ) ratsnestProvider->SetSeverities( drcJob->m_severity ); fpWarningsProvider->SetSeverities( drcJob->m_severity ); - bool wroteReport = DRC_TOOL::WriteReport( drcJob->m_outputFile, brd, units, markersProvider, - ratsnestProvider, fpWarningsProvider ); + m_reporter->Report( + wxString::Format( _( "Found %d violations\n" ), markersProvider->GetCount() ), + RPT_SEVERITY_INFO ); + m_reporter->Report( + wxString::Format( _( "Found %d unconnected items\n" ), ratsnestProvider->GetCount() ), + RPT_SEVERITY_INFO ); + m_reporter->Report( wxString::Format( _( "Found %d schematic parity issues\n" ), + fpWarningsProvider->GetCount() ), + RPT_SEVERITY_INFO ); + + DRC_REPORT reportWriter( brd, units, markersProvider, ratsnestProvider, fpWarningsProvider ); + + bool wroteReport = false; + if( drcJob->m_format == JOB_PCB_DRC::OUTPUT_FORMAT::JSON ) + wroteReport = reportWriter.WriteJsonReport( drcJob->m_outputFile ); + else + wroteReport = reportWriter.WriteTextReport( drcJob->m_outputFile ); if( !wroteReport ) { diff --git a/pcbnew/tools/drc_tool.cpp b/pcbnew/tools/drc_tool.cpp index 8bb43c4c07..76ef819330 100644 --- a/pcbnew/tools/drc_tool.cpp +++ b/pcbnew/tools/drc_tool.cpp @@ -294,77 +294,4 @@ void DRC_TOOL::setTransitions() Go( &DRC_TOOL::ExcludeMarker, ACTIONS::excludeMarker.MakeEvent() ); Go( &DRC_TOOL::CrossProbe, EVENTS::PointSelectedEvent ); Go( &DRC_TOOL::CrossProbe, EVENTS::SelectedEvent ); -} - - -bool DRC_TOOL::WriteReport( const wxString& aFullFileName, - BOARD* aBoard, - EDA_UNITS aReportUnits, - std::shared_ptr aMarkersProvider, - std::shared_ptr aRatsnestProvider, - std::shared_ptr aFpWarningsProvider ) -{ - FILE* fp = wxFopen( aFullFileName, wxT( "w" ) ); - - if( fp == nullptr ) - return false; - - std::map itemMap; - aBoard->FillItemMap( itemMap ); - - BOARD_DESIGN_SETTINGS& bds = aBoard->GetDesignSettings(); - UNITS_PROVIDER unitsProvider( pcbIUScale, aReportUnits ); - int count; - - fprintf( fp, "** Drc report for %s **\n", TO_UTF8( aBoard->GetFileName() ) ); - - wxDateTime now = wxDateTime::Now(); - - fprintf( fp, "** Created on %s **\n", TO_UTF8( now.Format( wxT( "%F %T" ) ) ) ); - - count = aMarkersProvider->GetCount(); - - fprintf( fp, "\n** Found %d DRC violations **\n", count ); - - for( int i = 0; i < count; ++i ) - { - const std::shared_ptr& item = aMarkersProvider->GetItem( i ); - SEVERITY severity = item->GetParent()->GetSeverity(); - - if( severity == RPT_SEVERITY_EXCLUSION ) - severity = bds.GetSeverity( item->GetErrorCode() ); - - fprintf( fp, "%s", TO_UTF8( item->ShowReport( &unitsProvider, severity, itemMap ) ) ); - } - - count = aRatsnestProvider->GetCount(); - - fprintf( fp, "\n** Found %d unconnected pads **\n", count ); - - for( int i = 0; i < count; ++i ) - { - const std::shared_ptr& item = aRatsnestProvider->GetItem( i ); - SEVERITY severity = bds.GetSeverity( item->GetErrorCode() ); - - fprintf( fp, "%s", TO_UTF8( item->ShowReport( &unitsProvider, severity, itemMap ) ) ); - } - - count = aFpWarningsProvider->GetCount(); - - fprintf( fp, "\n** Found %d Footprint errors **\n", count ); - - for( int i = 0; i < count; ++i ) - { - const std::shared_ptr& item = aFpWarningsProvider->GetItem( i ); - SEVERITY severity = bds.GetSeverity( item->GetErrorCode() ); - - fprintf( fp, "%s", TO_UTF8( item->ShowReport( &unitsProvider, severity, itemMap ) ) ); - } - - - fprintf( fp, "\n** End of Report **\n" ); - - fclose( fp ); - - return true; } \ No newline at end of file diff --git a/pcbnew/tools/drc_tool.h b/pcbnew/tools/drc_tool.h index 98caa21895..267b2700ee 100644 --- a/pcbnew/tools/drc_tool.h +++ b/pcbnew/tools/drc_tool.h @@ -95,17 +95,6 @@ public: int ExcludeMarker( const TOOL_EVENT& aEvent ); - /** - * Function writeReport - * outputs the MARKER items with commentary to an open text file. - * @param aFullFileName The text filename to write the report to. - * @return true if OK, false on error - */ - static bool WriteReport( const wxString& aFullFileName, BOARD* aBoard, EDA_UNITS aReportUnits, - std::shared_ptr aMarkersProvider, - std::shared_ptr aRatsnestProvider, - std::shared_ptr aFpWarningsProvider ); - private: ///< Set up handlers for various events. void setTransitions() override; diff --git a/resources/schemas/drc.v1.json b/resources/schemas/drc.v1.json new file mode 100644 index 0000000000..88c7e79276 --- /dev/null +++ b/resources/schemas/drc.v1.json @@ -0,0 +1,144 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://schemas.kicad.org/drc.v1.json", + "title": "KiCad DRC Report Schema", + "description": "KiCad Plugin and Content Manager repository and package metadata schema", + "type": "object", + "additionalProperties": false, + "properties": { + "source": { + "type": "string", + "description": "Source file path" + }, + "date": { + "type": "string", + "description": "Time at generation of report", + "format": "date-time" + }, + "kicad_version": { + "type": "string", + "description": "KiCad version used to generate the report", + "pattern": "^\\d{1,2}(\\.\\d{1,2}(\\.\\d{1,2})?)?$" + }, + "violations": { + "type": "array", + "items": { + "$ref": "#/definitions/Violation" + } + }, + "unconnected_items": { + "type": "array", + "items": { + "$ref": "#/definitions/Violation" + } + }, + "schematic_parity": { + "type": "array", + "items": { + "$ref": "#/definitions/Violation" + } + }, + "coordinate_units": { + "type": "string", + "description": "Units that all coordinates in this report are encoded in", + "enum": [ + "mm", + "mils", + "in" + ] + } + }, + "required": [ + "source", + "date", + "kicad_version", + "violations", + "unconnected_items", + "schematic_parity", + "coordinate_units", + ], + "definitions": { + "Violation": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "string", + "description": "KiCad type name for the violation" + }, + "description": { + "type": "string", + "description": "Description of the violation" + }, + "severity": { + "$ref": "#/definitions/Severity" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/AffectedItem" + } + } + }, + "required": [ + "type", + "description", + "severity", + "items" + ] + }, + "AffectedItem": { + "type": "object", + "additionalProperties": false, + "properties": { + "uuid": { + "$ref": "#/definitions/Uuid" + }, + "description": { + "type": "string", + "description": "Description of the item" + }, + "pos": { + "$ref": "#/definitions/Coordinate" + } + }, + "required": [ + "uuid", + "description", + "pos" + ] + }, + "Uuid": { + "type": "string", + "description": "Unique identifier of the item", + "pattern": "^[0-9a-fA-F]{8}\\b-[0-9a-fA-F]{4}\\b-[0-9a-fA-F]{4}\\b-[0-9a-fA-F]{4}\\b-[0-9a-fA-F]{12}$" + }, + "Severity": { + "type": "string", + "description": "Severity of the violation", + "enum": [ + "error", + "warning", + "ignore" + ] + }, + "Coordinate": { + "type": "object", + "additionalProperties": false, + "properties": { + "x": { + "type": "number", + "description": "x coordinate" + }, + "y": { + "type": "number", + "description": "y coordinate" + } + }, + "required": [ + "x", + "y" + ] + } + } +} \ No newline at end of file