ADDED: DRC JSON report
This commit is contained in:
parent
64a7bad56e
commit
14a0fa435c
|
@ -266,7 +266,7 @@ void NOTIFICATIONS_MANAGER::Load()
|
||||||
{
|
{
|
||||||
nlohmann::json saved_json;
|
nlohmann::json saved_json;
|
||||||
|
|
||||||
std::ifstream saved_json_stream( m_destFileName.GetFullPath().ToUTF8() );
|
std::ifstream saved_json_stream( m_destFileName.GetFullPath().fn_str() );
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -289,7 +289,7 @@ void NOTIFICATIONS_MANAGER::Load()
|
||||||
|
|
||||||
void NOTIFICATIONS_MANAGER::Save()
|
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 );
|
nlohmann::json saveJson = nlohmann::json( m_notifications );
|
||||||
jsonFileStream << std::setw( 4 ) << saveJson << std::endl;
|
jsonFileStream << std::setw( 4 ) << saveJson << std::endl;
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include <marker_base.h>
|
#include <marker_base.h>
|
||||||
#include <eda_draw_frame.h>
|
#include <eda_draw_frame.h>
|
||||||
#include <rc_item.h>
|
#include <rc_item.h>
|
||||||
|
#include <rc_json_schema.h>
|
||||||
#include <eda_item.h>
|
#include <eda_item.h>
|
||||||
#include <base_units.h>
|
#include <base_units.h>
|
||||||
|
|
||||||
|
@ -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,
|
wxString getSeverityString( SEVERITY aSeverity )
|
||||||
const std::map<KIID, EDA_ITEM*>& aItemMap ) const
|
|
||||||
{
|
{
|
||||||
wxString severity;
|
wxString severity;
|
||||||
|
|
||||||
switch( aSeverity )
|
switch( aSeverity )
|
||||||
{
|
{
|
||||||
case RPT_SEVERITY_ERROR: severity = wxT( "Severity: error" ); break;
|
case RPT_SEVERITY_ERROR: severity = wxS( "error" ); break;
|
||||||
case RPT_SEVERITY_WARNING: severity = wxT( "Severity: warning" ); break;
|
case RPT_SEVERITY_WARNING: severity = wxS( "warning" ); break;
|
||||||
case RPT_SEVERITY_ACTION: severity = wxT( "Severity: action" ); break;
|
case RPT_SEVERITY_ACTION: severity = wxS( "action" ); break;
|
||||||
case RPT_SEVERITY_INFO: severity = wxT( "Severity: info" ); break;
|
case RPT_SEVERITY_INFO: severity = wxS( "info" ); break;
|
||||||
case RPT_SEVERITY_EXCLUSION: severity = wxT( "Severity: exclusion" ); break;
|
case RPT_SEVERITY_EXCLUSION: severity = wxS( "exclusion" ); break;
|
||||||
case RPT_SEVERITY_DEBUG: severity = wxT( "Severity: debug" ); break;
|
case RPT_SEVERITY_DEBUG: severity = wxS( "debug" ); break;
|
||||||
default: ;
|
default:;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
return severity;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wxString RC_ITEM::ShowReport( UNITS_PROVIDER* aUnitsProvider, SEVERITY aSeverity,
|
||||||
|
const std::map<KIID, EDA_ITEM*>& aItemMap ) const
|
||||||
|
{
|
||||||
|
wxString severity = getSeverityString( aSeverity );
|
||||||
|
|
||||||
if( m_parent && m_parent->IsExcluded() )
|
if( m_parent && m_parent->IsExcluded() )
|
||||||
severity += wxT( " (excluded)" );
|
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<KIID, EDA_ITEM*>& 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 )
|
KIID RC_TREE_MODEL::ToUUID( wxDataViewItem aItem )
|
||||||
{
|
{
|
||||||
const RC_TREE_NODE* node = RC_TREE_MODEL::ToNode( aItem );
|
const RC_TREE_NODE* node = RC_TREE_MODEL::ToNode( aItem );
|
||||||
|
|
|
@ -190,6 +190,7 @@ const std::string TextFileExtension( "txt" );
|
||||||
const std::string MarkdownFileExtension( "md" );
|
const std::string MarkdownFileExtension( "md" );
|
||||||
const std::string CsvFileExtension( "csv" );
|
const std::string CsvFileExtension( "csv" );
|
||||||
const std::string XmlFileExtension( "xml" );
|
const std::string XmlFileExtension( "xml" );
|
||||||
|
const std::string JsonFileExtension( "json" );
|
||||||
|
|
||||||
const wxString GerberFileExtensionsRegex( "(gbr|gko|pho|(g[tb][alops])|(gm?\\d\\d*)|(gp[tb]))" );
|
const wxString GerberFileExtensionsRegex( "(gbr|gko|pho|(g[tb][alops])|(gm?\\d\\d*)|(gp[tb]))" );
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,10 @@ class RC_ITEM;
|
||||||
class EDA_ITEM;
|
class EDA_ITEM;
|
||||||
class EDA_DRAW_FRAME;
|
class EDA_DRAW_FRAME;
|
||||||
|
|
||||||
|
namespace RC_JSON
|
||||||
|
{
|
||||||
|
struct VIOLATION;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provide an abstract interface of a RC_ITEM* list manager.
|
* Provide an abstract interface of a RC_ITEM* list manager.
|
||||||
|
@ -133,6 +137,19 @@ public:
|
||||||
virtual wxString ShowReport( UNITS_PROVIDER* aUnitsProvider, SEVERITY aSeverity,
|
virtual wxString ShowReport( UNITS_PROVIDER* aUnitsProvider, SEVERITY aSeverity,
|
||||||
const std::map<KIID, EDA_ITEM*>& aItemMap ) const;
|
const std::map<KIID, EDA_ITEM*>& 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<KIID, EDA_ITEM*>& aItemMap ) const;
|
||||||
|
|
||||||
int GetErrorCode() const { return m_errorCode; }
|
int GetErrorCode() const { return m_errorCode; }
|
||||||
void SetErrorCode( int aCode ) { m_errorCode = aCode; }
|
void SetErrorCode( int aCode ) { m_errorCode = aCode; }
|
||||||
|
|
||||||
|
@ -274,6 +291,7 @@ public:
|
||||||
protected:
|
protected:
|
||||||
void rebuildModel( std::shared_ptr<RC_ITEMS_PROVIDER> aProvider, int aSeverities );
|
void rebuildModel( std::shared_ptr<RC_ITEMS_PROVIDER> aProvider, int aSeverities );
|
||||||
void onSizeView( wxSizeEvent& aEvent );
|
void onSizeView( wxSizeEvent& aEvent );
|
||||||
|
wxString getSeverityString( SEVERITY aSeverity );
|
||||||
|
|
||||||
EDA_DRAW_FRAME* m_editFrame;
|
EDA_DRAW_FRAME* m_editFrame;
|
||||||
wxDataViewCtrl* m_view;
|
wxDataViewCtrl* m_view;
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef RC_JSON_SCHEMA_H
|
||||||
|
#define RC_JSON_SCHEMA_H
|
||||||
|
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
#include <wx/string.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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<AFFECTED_ITEM> 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<VIOLATION> violations;
|
||||||
|
std::vector<VIOLATION> unconnected_items;
|
||||||
|
std::vector<VIOLATION> 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<VIOLATION> violations;
|
||||||
|
};
|
||||||
|
|
||||||
|
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE( ERC_SHEET, uuid, path, violations )
|
||||||
|
|
||||||
|
struct ERC_REPORT : REPORT_BASE
|
||||||
|
{
|
||||||
|
ERC_REPORT() { type = wxS( "erc" ); }
|
||||||
|
|
||||||
|
std::vector<ERC_SHEET> sheets;
|
||||||
|
};
|
||||||
|
|
||||||
|
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE( ERC_REPORT, source, date, kicad_version, sheets,
|
||||||
|
coordinate_units )
|
||||||
|
|
||||||
|
} // namespace RC_JSON
|
||||||
|
|
||||||
|
#endif
|
|
@ -176,6 +176,7 @@ extern const std::string TextFileExtension;
|
||||||
extern const std::string MarkdownFileExtension;
|
extern const std::string MarkdownFileExtension;
|
||||||
extern const std::string CsvFileExtension;
|
extern const std::string CsvFileExtension;
|
||||||
extern const std::string XmlFileExtension;
|
extern const std::string XmlFileExtension;
|
||||||
|
extern const std::string JsonFileExtension;
|
||||||
|
|
||||||
extern const wxString GerberFileExtensionsRegex;
|
extern const wxString GerberFileExtensionsRegex;
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ CLI::PCB_DRC_COMMAND::PCB_DRC_COMMAND() : EXPORT_PCB_BASE_COMMAND( "drc" )
|
||||||
{
|
{
|
||||||
m_argParser.add_argument( ARG_FORMAT )
|
m_argParser.add_argument( ARG_FORMAT )
|
||||||
.default_value( std::string( "report" ) )
|
.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 )
|
m_argParser.add_argument( ARG_ALL_TRACK_ERRORS )
|
||||||
.help( UTF8STDSTR( _( "Report all errors for each track" ) ) )
|
.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;
|
drcJob->m_format = JOB_PCB_DRC::OUTPUT_FORMAT::REPORT;
|
||||||
}
|
}
|
||||||
|
else if( format == "json" )
|
||||||
|
{
|
||||||
|
drcJob->m_format = JOB_PCB_DRC::OUTPUT_FORMAT::JSON;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
wxFprintf( stderr, _( "Invalid report format\n" ) );
|
wxFprintf( stderr, _( "Invalid report format\n" ) );
|
||||||
|
|
|
@ -233,6 +233,7 @@ set( PCBNEW_MICROWAVE_SRCS
|
||||||
|
|
||||||
set( PCBNEW_DRC_SRCS
|
set( PCBNEW_DRC_SRCS
|
||||||
drc/drc_interactive_courtyard_clearance.cpp
|
drc/drc_interactive_courtyard_clearance.cpp
|
||||||
|
drc/drc_report.cpp
|
||||||
drc/drc_test_provider.cpp
|
drc/drc_test_provider.cpp
|
||||||
drc/drc_test_provider_annular_width.cpp
|
drc/drc_test_provider_annular_width.cpp
|
||||||
drc/drc_test_provider_disallow.cpp
|
drc/drc_test_provider_disallow.cpp
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include <macros.h>
|
#include <macros.h>
|
||||||
#include <pad.h>
|
#include <pad.h>
|
||||||
#include <drc/drc_item.h>
|
#include <drc/drc_item.h>
|
||||||
|
#include <drc/drc_report.h>
|
||||||
#include <connectivity/connectivity_data.h>
|
#include <connectivity/connectivity_data.h>
|
||||||
#include <connectivity/connectivity_algo.h>
|
#include <connectivity/connectivity_algo.h>
|
||||||
#include <drawing_sheet/ds_proxy_view_item.h>
|
#include <drawing_sheet/ds_proxy_view_item.h>
|
||||||
|
@ -869,7 +870,10 @@ void DIALOG_DRC::OnSaveReport( wxCommandEvent& aEvent )
|
||||||
fn.MakeAbsolute( prj_path );
|
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<br>" ),
|
m_messages->Report( wxString::Format( _( "Report file '%s' created<br>" ),
|
||||||
fn.GetFullPath() ) );
|
fn.GetFullPath() ) );
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <wx/string.h>
|
||||||
|
|
||||||
|
#include <board.h>
|
||||||
|
#include <board_design_settings.h>
|
||||||
|
#include <build_version.h>
|
||||||
|
#include "drc_report.h"
|
||||||
|
#include <drc/drc_item.h>
|
||||||
|
#include <fstream>
|
||||||
|
#include <macros.h>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
#include <rc_json_schema.h>
|
||||||
|
|
||||||
|
|
||||||
|
DRC_REPORT::DRC_REPORT(BOARD* aBoard, EDA_UNITS aReportUnits,
|
||||||
|
std::shared_ptr<RC_ITEMS_PROVIDER> aMarkersProvider,
|
||||||
|
std::shared_ptr<RC_ITEMS_PROVIDER> aRatsnestProvider,
|
||||||
|
std::shared_ptr<RC_ITEMS_PROVIDER> 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<KIID, EDA_ITEM*> 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<RC_ITEM>& 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<RC_ITEM>& 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<RC_ITEM>& 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<KIID, EDA_ITEM*> 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<RC_ITEM>& 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<RC_ITEM>& 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<RC_ITEM>& 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;
|
||||||
|
}
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DRC_REPORT_H
|
||||||
|
#define DRC_REPORT_H
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <eda_units.h>
|
||||||
|
#include <wx/string.h>
|
||||||
|
|
||||||
|
class BOARD;
|
||||||
|
class RC_ITEMS_PROVIDER;
|
||||||
|
|
||||||
|
class DRC_REPORT
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DRC_REPORT( BOARD* aBoard,
|
||||||
|
EDA_UNITS aReportUnits,
|
||||||
|
std::shared_ptr<RC_ITEMS_PROVIDER> aMarkersProvider,
|
||||||
|
std::shared_ptr<RC_ITEMS_PROVIDER> aRatsnestProvider,
|
||||||
|
std::shared_ptr<RC_ITEMS_PROVIDER> aFpWarningsProvider );
|
||||||
|
|
||||||
|
bool WriteTextReport( const wxString& aFullFileName );
|
||||||
|
bool WriteJsonReport( const wxString& aFullFileName );
|
||||||
|
|
||||||
|
private:
|
||||||
|
BOARD* m_board;
|
||||||
|
EDA_UNITS m_reportUnits;
|
||||||
|
std::shared_ptr<RC_ITEMS_PROVIDER> m_markersProvider;
|
||||||
|
std::shared_ptr<RC_ITEMS_PROVIDER> m_ratsnestProvider;
|
||||||
|
std::shared_ptr<RC_ITEMS_PROVIDER> m_fpWarningsProvider;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -23,6 +23,7 @@
|
||||||
#include <board_commit.h>
|
#include <board_commit.h>
|
||||||
#include <board_design_settings.h>
|
#include <board_design_settings.h>
|
||||||
#include <drc/drc_item.h>
|
#include <drc/drc_item.h>
|
||||||
|
#include <drc/drc_report.h>
|
||||||
#include <drawing_sheet/ds_proxy_view_item.h>
|
#include <drawing_sheet/ds_proxy_view_item.h>
|
||||||
#include <jobs/job_fp_export_svg.h>
|
#include <jobs/job_fp_export_svg.h>
|
||||||
#include <jobs/job_fp_upgrade.h>
|
#include <jobs/job_fp_upgrade.h>
|
||||||
|
@ -866,6 +867,10 @@ int PCBNEW_JOBS_HANDLER::JobExportDrc( JOB* aJob )
|
||||||
{
|
{
|
||||||
wxFileName fn = brd->GetFileName();
|
wxFileName fn = brd->GetFileName();
|
||||||
fn.SetName( fn.GetName() );
|
fn.SetName( fn.GetName() );
|
||||||
|
|
||||||
|
if( drcJob->m_format == JOB_PCB_DRC::OUTPUT_FORMAT::JSON )
|
||||||
|
fn.SetExt( JsonFileExtension );
|
||||||
|
else
|
||||||
fn.SetExt( ReportFileExtension );
|
fn.SetExt( ReportFileExtension );
|
||||||
|
|
||||||
drcJob->m_outputFile = fn.GetFullName();
|
drcJob->m_outputFile = fn.GetFullName();
|
||||||
|
@ -922,8 +927,23 @@ int PCBNEW_JOBS_HANDLER::JobExportDrc( JOB* aJob )
|
||||||
ratsnestProvider->SetSeverities( drcJob->m_severity );
|
ratsnestProvider->SetSeverities( drcJob->m_severity );
|
||||||
fpWarningsProvider->SetSeverities( drcJob->m_severity );
|
fpWarningsProvider->SetSeverities( drcJob->m_severity );
|
||||||
|
|
||||||
bool wroteReport = DRC_TOOL::WriteReport( drcJob->m_outputFile, brd, units, markersProvider,
|
m_reporter->Report(
|
||||||
ratsnestProvider, fpWarningsProvider );
|
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 )
|
if( !wroteReport )
|
||||||
{
|
{
|
||||||
|
|
|
@ -295,76 +295,3 @@ void DRC_TOOL::setTransitions()
|
||||||
Go( &DRC_TOOL::CrossProbe, EVENTS::PointSelectedEvent );
|
Go( &DRC_TOOL::CrossProbe, EVENTS::PointSelectedEvent );
|
||||||
Go( &DRC_TOOL::CrossProbe, EVENTS::SelectedEvent );
|
Go( &DRC_TOOL::CrossProbe, EVENTS::SelectedEvent );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool DRC_TOOL::WriteReport( const wxString& aFullFileName,
|
|
||||||
BOARD* aBoard,
|
|
||||||
EDA_UNITS aReportUnits,
|
|
||||||
std::shared_ptr<RC_ITEMS_PROVIDER> aMarkersProvider,
|
|
||||||
std::shared_ptr<RC_ITEMS_PROVIDER> aRatsnestProvider,
|
|
||||||
std::shared_ptr<RC_ITEMS_PROVIDER> aFpWarningsProvider )
|
|
||||||
{
|
|
||||||
FILE* fp = wxFopen( aFullFileName, wxT( "w" ) );
|
|
||||||
|
|
||||||
if( fp == nullptr )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
std::map<KIID, EDA_ITEM*> 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<RC_ITEM>& 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<RC_ITEM>& 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<RC_ITEM>& 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;
|
|
||||||
}
|
|
|
@ -95,17 +95,6 @@ public:
|
||||||
|
|
||||||
int ExcludeMarker( const TOOL_EVENT& aEvent );
|
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<RC_ITEMS_PROVIDER> aMarkersProvider,
|
|
||||||
std::shared_ptr<RC_ITEMS_PROVIDER> aRatsnestProvider,
|
|
||||||
std::shared_ptr<RC_ITEMS_PROVIDER> aFpWarningsProvider );
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
///< Set up handlers for various events.
|
///< Set up handlers for various events.
|
||||||
void setTransitions() override;
|
void setTransitions() override;
|
||||||
|
|
|
@ -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"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue