You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

171 lines
5.3 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2023 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 along
  17. * with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include <wx/ffile.h>
  20. #include <wx/string.h>
  21. #include <sch_screen.h>
  22. #include <sch_marker.h>
  23. #include <schematic.h>
  24. #include <string_utils.h>
  25. #include <build_version.h>
  26. #include "erc_report.h"
  27. #include <eda_units.h>
  28. #include <erc.h>
  29. #include <fstream>
  30. #include <macros.h>
  31. #include <nlohmann/json.hpp>
  32. #include <rc_json_schema.h>
  33. ERC_REPORT::ERC_REPORT( SCHEMATIC* aSchematic, EDA_UNITS aReportUnits ) :
  34. m_sch( aSchematic ),
  35. m_reportUnits( aReportUnits )
  36. {
  37. }
  38. wxString ERC_REPORT::GetTextReport()
  39. {
  40. UNITS_PROVIDER unitsProvider( schIUScale, m_reportUnits );
  41. wxString msg = wxString::Format( _( "ERC report (%s, Encoding UTF8)\n" ),
  42. GetISO8601CurrentDateTime() );
  43. std::map<KIID, EDA_ITEM*> itemMap;
  44. int err_count = 0;
  45. int warn_count = 0;
  46. int total_count = 0;
  47. SCH_SHEET_LIST sheetList = m_sch->GetSheets();
  48. sheetList.FillItemMap( itemMap );
  49. ERC_SETTINGS& settings = m_sch->ErcSettings();
  50. for( unsigned i = 0; i < sheetList.size(); i++ )
  51. {
  52. msg << wxString::Format( _( "\n***** Sheet %s\n" ), sheetList[i].PathHumanReadable() );
  53. for( SCH_ITEM* aItem : sheetList[i].LastScreen()->Items().OfType( SCH_MARKER_T ) )
  54. {
  55. const SCH_MARKER* marker = static_cast<const SCH_MARKER*>( aItem );
  56. RC_ITEM* item = marker->GetRCItem().get();
  57. SEVERITY severity = settings.GetSeverity( item->GetErrorCode() );
  58. if( marker->GetMarkerType() != MARKER_BASE::MARKER_ERC )
  59. continue;
  60. total_count++;
  61. switch( severity )
  62. {
  63. case RPT_SEVERITY_ERROR: err_count++; break;
  64. case RPT_SEVERITY_WARNING: warn_count++; break;
  65. default: break;
  66. }
  67. msg << marker->GetRCItem()->ShowReport( &unitsProvider, severity, itemMap );
  68. }
  69. }
  70. msg << wxString::Format( _( "\n ** ERC messages: %d Errors %d Warnings %d\n" ), total_count,
  71. err_count, warn_count );
  72. return msg;
  73. }
  74. bool ERC_REPORT::WriteTextReport( const wxString& aFullFileName )
  75. {
  76. wxFFile file( aFullFileName, wxT( "wt" ) );
  77. if( !file.IsOpened() )
  78. return false;
  79. file.Write( GetTextReport() );
  80. // wxFFile dtor will close the file.
  81. return true;
  82. }
  83. bool ERC_REPORT::WriteJsonReport( const wxString& aFullFileName )
  84. {
  85. std::ofstream jsonFileStream( aFullFileName.fn_str() );
  86. UNITS_PROVIDER unitsProvider( pcbIUScale, m_reportUnits );
  87. std::map<KIID, EDA_ITEM*> itemMap;
  88. RC_JSON::ERC_REPORT reportHead;
  89. wxFileName fn( m_sch->GetFileName() );
  90. reportHead.$schema = "https://schemas.kicad.org/erc.v1.json";
  91. reportHead.source = fn.GetFullName();
  92. reportHead.date = GetISO8601CurrentDateTime();
  93. reportHead.kicad_version = GetMajorMinorPatchVersion();
  94. reportHead.coordinate_units = EDA_UNIT_UTILS::GetLabel( m_reportUnits );
  95. int err_count = 0;
  96. int warn_count = 0;
  97. int total_count = 0;
  98. SCH_SHEET_LIST sheetList = m_sch->GetSheets();
  99. sheetList.FillItemMap( itemMap );
  100. ERC_SETTINGS& settings = m_sch->ErcSettings();
  101. for( unsigned i = 0; i < sheetList.size(); i++ )
  102. {
  103. RC_JSON::ERC_SHEET jsonSheet;
  104. jsonSheet.path = sheetList[i].PathHumanReadable();
  105. jsonSheet.uuid_path = sheetList[i].Path().AsString();
  106. for( SCH_ITEM* aItem : sheetList[i].LastScreen()->Items().OfType( SCH_MARKER_T ) )
  107. {
  108. const SCH_MARKER* marker = static_cast<const SCH_MARKER*>( aItem );
  109. RC_ITEM* item = marker->GetRCItem().get();
  110. SEVERITY severity = settings.GetSeverity( item->GetErrorCode() );
  111. if( marker->GetMarkerType() != MARKER_BASE::MARKER_ERC )
  112. continue;
  113. total_count++;
  114. switch( severity )
  115. {
  116. case RPT_SEVERITY_ERROR: err_count++; break;
  117. case RPT_SEVERITY_WARNING: warn_count++; break;
  118. default: break;
  119. }
  120. RC_JSON::VIOLATION violation;
  121. marker->GetRCItem()->GetJsonViolation( violation, &unitsProvider, severity, itemMap );
  122. jsonSheet.violations.push_back( violation );
  123. }
  124. reportHead.sheets.push_back( jsonSheet );
  125. }
  126. nlohmann::json saveJson = nlohmann::json( reportHead );
  127. jsonFileStream << std::setw( 4 ) << saveJson << std::endl;
  128. jsonFileStream.flush();
  129. jsonFileStream.close();
  130. return true;
  131. }