KiCad PCB EDA Suite
Loading...
Searching...
No Matches
erc_report.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20#include <wx/ffile.h>
21#include <wx/string.h>
22
23#include <locale_io.h>
24#include <sch_screen.h>
25#include <sch_marker.h>
26#include <schematic.h>
27#include <string_utils.h>
28#include <build_version.h>
29#include "erc_report.h"
30#include <eda_units.h>
31#include <erc/erc.h>
32#include <fstream>
33#include <macros.h>
34#include <json_common.h>
35#include <rc_json_schema.h>
37
38
39ERC_REPORT::ERC_REPORT( SCHEMATIC* aSchematic, EDA_UNITS aReportUnits,
40 std::shared_ptr<RC_ITEMS_PROVIDER> aMarkersProvider ) :
41 m_sch( aSchematic ),
42 m_reportUnits( aReportUnits ),
43 m_markersProvider( std::move( aMarkersProvider ) ),
45{
47 {
48 // When no provider is supplied, fall back to creating one with default severities.
49 // This allows test code to get a basic report without needing to set up a provider.
50 m_markersProvider = std::make_shared<SHEETLIST_ERC_ITEMS_PROVIDER>( m_sch );
52 }
53
54 m_reportedSeverities = m_markersProvider->GetSeverities();
55}
56
57
59{
60 // We need the global LOCALE_IO here in order to
61 // write the report in the c-locale.
62 LOCALE_IO locale;
63 UNITS_PROVIDER unitsProvider( schIUScale, m_reportUnits );
64
65 wxString msg = wxString::Format( wxT( "ERC report (%s, Encoding UTF8)\n" ),
67
68 msg += wxString::Format( wxT( "Report includes: %s\n" ),
70
71 std::map<KIID, EDA_ITEM*> itemMap;
72
73 int err_count = 0;
74 int warn_count = 0;
75 int total_count = 0;
76 SCH_SHEET_LIST sheetList = m_sch->BuildSheetListSortedByPageNumbers();
77
78 sheetList.FillItemMap( itemMap );
79
80 ERC_SETTINGS& settings = m_sch->ErcSettings();
81
82 std::map<SCH_SHEET_PATH, std::vector<ERC_ITEM*>> orderedItems;
83
84 for( int i = 0; i < m_markersProvider->GetCount(); ++i )
85 {
86 if( auto item = dynamic_cast<ERC_ITEM*>( m_markersProvider->GetItem( i ).get() ) )
87 {
88 if( item->MainItemHasSheetPath() )
89 orderedItems[item->GetMainItemSheetPath()].emplace_back( item );
90 else if( item->IsSheetSpecific() )
91 orderedItems[item->GetSpecificSheetPath()].emplace_back( item );
92 else
93 orderedItems[sheetList[0]].emplace_back( item );
94 }
95 }
96
97 for( unsigned i = 0; i < sheetList.size(); i++ )
98 {
99 msg << wxString::Format( wxT( "\n***** Sheet %s\n" ), sheetList[i].PathHumanReadable() );
100
101 for( ERC_ITEM* item : orderedItems[sheetList[i]] )
102 {
103 SEVERITY severity = settings.GetSeverity( item->GetErrorCode() );
104
105 total_count++;
106
107 switch( severity )
108 {
109 case RPT_SEVERITY_ERROR: err_count++; break;
110 case RPT_SEVERITY_WARNING: warn_count++; break;
111 default: break;
112 }
113
114 msg << item->ShowReport( &unitsProvider, severity, itemMap );
115 }
116 }
117
118 msg << wxString::Format( wxT( "\n ** ERC messages: %d Errors %d Warnings %d\n" ),
119 total_count,
120 err_count,
121 warn_count );
122
123 msg << wxT( "\n ** Ignored checks:\n" );
124
125 bool hasIgnored = false;
126
127 for( const RC_ITEM& item : ERC_ITEM::GetItemsWithSeverities() )
128 {
129 int code = item.GetErrorCode();
130
131 if( code > 0 && settings.GetSeverity( code ) == RPT_SEVERITY_IGNORE )
132 {
133 msg << wxString::Format( wxT( " - %s\n" ), item.GetErrorMessage( false ) );
134 hasIgnored = true;
135 }
136 }
137
138 if( !hasIgnored )
139 msg << wxT( " - " ) << wxT( "None" ) << wxT( "\n" );
140
141 return msg;
142}
143
144
145bool ERC_REPORT::WriteTextReport( const wxString& aFullFileName )
146{
147 wxFFile file( aFullFileName, wxT( "wt" ) );
148
149 if( !file.IsOpened() )
150 return false;
151
152 file.Write( GetTextReport() );
153
154 // wxFFile dtor will close the file.
155 return true;
156}
157
158
159bool ERC_REPORT::WriteJsonReport( const wxString& aFullFileName )
160{
161 std::ofstream jsonFileStream( aFullFileName.fn_str() );
162
163 UNITS_PROVIDER unitsProvider( pcbIUScale, m_reportUnits );
164 std::map<KIID, EDA_ITEM*> itemMap;
165
166 RC_JSON::ERC_REPORT reportHead;
167 wxFileName fn( m_sch->GetFileName() );
168 reportHead.$schema = "https://schemas.kicad.org/erc.v1.json";
169 reportHead.source = fn.GetFullName();
170 reportHead.date = GetISO8601CurrentDateTime();
173
174 // Document which severities are included in this report
176 reportHead.included_severities.push_back( wxS( "error" ) );
177
179 reportHead.included_severities.push_back( wxS( "warning" ) );
180
182 reportHead.included_severities.push_back( wxS( "exclusion" ) );
183
184 SCH_SHEET_LIST sheetList = m_sch->Hierarchy();
185 sheetList.FillItemMap( itemMap );
186
187 ERC_SETTINGS& settings = m_sch->ErcSettings();
188
189 std::map<SCH_SHEET_PATH, std::vector<ERC_ITEM*>> orderedItems;
190
191 for( int i = 0; i < m_markersProvider->GetCount(); ++i )
192 {
193 if( auto item = dynamic_cast<ERC_ITEM*>( m_markersProvider->GetItem( i ).get() ) )
194 {
195 if( item->MainItemHasSheetPath() )
196 orderedItems[item->GetMainItemSheetPath()].emplace_back( item );
197 else if( item->IsSheetSpecific() )
198 orderedItems[item->GetSpecificSheetPath()].emplace_back( item );
199 else
200 orderedItems[sheetList[0]].emplace_back( item );
201 }
202 }
203
204 for( unsigned i = 0; i < sheetList.size(); i++ )
205 {
206 RC_JSON::ERC_SHEET jsonSheet;
207 jsonSheet.path = sheetList[i].PathHumanReadable();
208 jsonSheet.uuid_path = sheetList[i].Path().AsString();
209
210 for( ERC_ITEM* item : orderedItems[sheetList[i]] )
211 {
212 SEVERITY severity = settings.GetSeverity( item->GetErrorCode() );
213
214 RC_JSON::VIOLATION violation;
215 item->GetJsonViolation( violation, &unitsProvider, severity, itemMap );
216
217 jsonSheet.violations.push_back( violation );
218 }
219
220 reportHead.sheets.push_back( jsonSheet );
221 }
222
223 for( const RC_ITEM& item : ERC_ITEM::GetItemsWithSeverities() )
224 {
225 int code = item.GetErrorCode();
226
227 if( code > 0 && settings.GetSeverity( code ) == RPT_SEVERITY_IGNORE )
228 {
229 RC_JSON::IGNORED_CHECK ignoredCheck;
230 ignoredCheck.key = item.GetSettingsKey();
231 ignoredCheck.description = item.GetErrorMessage( false );
232 reportHead.ignored_checks.push_back( ignoredCheck );
233 }
234 }
235
236 nlohmann::json saveJson = nlohmann::json( reportHead );
237 jsonFileStream << std::setw( 4 ) << saveJson << std::endl;
238 jsonFileStream.flush();
239 jsonFileStream.close();
240
241 return true;
242}
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:123
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:121
wxString GetMajorMinorPatchVersion()
Get the major, minor and patch version in a string major.minor.patch This is extracted by CMake from ...
static std::vector< std::reference_wrapper< RC_ITEM > > GetItemsWithSeverities()
Definition erc_item.h:72
EDA_UNITS m_reportUnits
Definition erc_report.h:59
ERC_REPORT(SCHEMATIC *aSchematic, EDA_UNITS aReportUnits, std::shared_ptr< RC_ITEMS_PROVIDER > aMarkersProvider=nullptr)
int m_reportedSeverities
Definition erc_report.h:61
wxString GetTextReport()
Returns the ERC report in "text" (human readable) format in the C-locale.
SCHEMATIC * m_sch
Definition erc_report.h:58
bool WriteJsonReport(const wxString &aFullFileName)
Writes a JSON formatted ERC Report to the given file path in the c-locale.
std::shared_ptr< RC_ITEMS_PROVIDER > m_markersProvider
Definition erc_report.h:60
bool WriteTextReport(const wxString &aFullFileName)
Writes the text report also available via GetTextReport directly to a given file path.
Container for ERC settings.
SEVERITY GetSeverity(int aErrorCode) const
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition locale_io.h:37
A holder for a rule check item, DRC in Pcbnew or ERC in Eeschema.
Definition rc_item.h:79
Holds all the data relating to one schematic.
Definition schematic.h:148
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
void FillItemMap(std::map< KIID, EDA_ITEM * > &aMap)
Fill an item cache for temporary use when many items need to be fetched.
EDA_UNITS
Definition eda_units.h:44
This file contains miscellaneous commonly used macros and functions.
KICOMMON_API wxString GetLabel(EDA_UNITS aUnits, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
Get the units string for a given units type.
STL namespace.
wxString formatSeverities(int aSeverities)
Convert a severity mask to a human-readable comma-separated string.
SEVERITY
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_EXCLUSION
@ RPT_SEVERITY_IGNORE
wxString GetISO8601CurrentDateTime()
std::vector< wxString > included_severities
std::vector< ERC_SHEET > sheets
std::vector< IGNORED_CHECK > ignored_checks