kicad-validity B3+C+S: revert toast, corpus lint, .kicad_mod tier
B3 (editor): kicad-binding observes kdoc_meta.revertNonce (deduped, like seedNonce) → DOC_REVERTED_EVENT → WasmTool doc-reverted-toast (15 s, data-testid for the deferred e2e check). C: tests/tools/corpus-lint.ts (npm run corpus:lint) — kicad_tools --lint over the fixture corpora raw + shared-codec round-trips (docToFile(fileToDoc(x))); the E3/wrapInBoardEnvelope-class gate. Skips when output/kicad_tools.js isn't built; CI step lands when kicad_tools joins the CI app set. 7 fixtures / 7 round-trips green. S: --lint + --resave gain the .kicad_mod tier (pcbToolsLintFootprint / pcbToolsResaveFootprint; writer needs CTL_FOR_LIBRARY or the board flags strip the (version) header). Verified: qa footprint round-trip lints clean, resave stamps 20260206, garbage exits 1. Also bumps pcbjam-shared (mergeYUpdates for the bisect pass). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HLua64PCVwkQ1hpWdaf1Gm
This commit is contained in:
parent
b18b0a6a08
commit
fb2aa2759d
8 changed files with 323 additions and 7 deletions
|
|
@ -14,9 +14,9 @@
|
|||
* eeschema side (sym_convert_main.cpp) — everything else:
|
||||
* kicad_tools --convert-lib <input.lib> <output.kicad_sym>
|
||||
* kicad_tools --lint [--strict] <file> [<file>...]
|
||||
* (.kicad_pcb files get a FULL parse here — the pcbnew
|
||||
* parser is linked; the lint driver calls back into
|
||||
* pcbToolsLintBoard on the pcb side)
|
||||
* (.kicad_pcb/.kicad_mod get a FULL parse here — the
|
||||
* pcbnew parser is linked; the lint driver calls back
|
||||
* into pcbToolsLintBoard/pcbToolsLintFootprint)
|
||||
* kicad_tools --resave <file> <outdir>
|
||||
* (full parse + rewrite in the current file-format
|
||||
* version — kicad-validity 0001; .kicad_pcb via the
|
||||
|
|
|
|||
|
|
@ -69,8 +69,11 @@
|
|||
#include <layer_ids.h>
|
||||
#include <lset.h>
|
||||
#include <libraries/library_manager.h>
|
||||
#include <footprint.h>
|
||||
#include <pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.h>
|
||||
#include <pcb_io/pcb_io_mgr.h>
|
||||
#include <pcb_marker.h>
|
||||
#include <richio.h>
|
||||
#include <pcb_plotter.h>
|
||||
#include <pcbplot.h>
|
||||
#include <pgm_base.h>
|
||||
|
|
@ -681,6 +684,120 @@ int pcbToolsLintBoard( const char* aInPath, std::string& aError )
|
|||
}
|
||||
|
||||
|
||||
// Full-parse footprint lint for the merged image's --lint driver
|
||||
// (kicad-validity 0001 S): parse one .kicad_mod via the s-expr plugin's
|
||||
// ImportFootprint. Returns the pad count, or -1 with aError filled.
|
||||
int pcbToolsLintFootprint( const char* aInPath, std::string& aError )
|
||||
{
|
||||
wxFileName fn( wxString::FromUTF8( aInPath ) );
|
||||
fn.MakeAbsolute();
|
||||
|
||||
kiRuntime();
|
||||
|
||||
try
|
||||
{
|
||||
PCB_IO_KICAD_SEXPR plugin;
|
||||
wxString name;
|
||||
std::unique_ptr<FOOTPRINT> fp( plugin.ImportFootprint( fn.GetFullPath(), name ) );
|
||||
|
||||
if( !fp )
|
||||
{
|
||||
aError = std::string( aInPath ) + ": error: not a footprint file";
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (int) fp->Pads().size();
|
||||
}
|
||||
catch( PARSE_ERROR& pe )
|
||||
{
|
||||
char buf[1024];
|
||||
std::snprintf( buf, sizeof( buf ), "%s:%d:%d: error: %s", aInPath, pe.lineNumber,
|
||||
pe.byteIndex, (const char*) pe.ParseProblem().ToUTF8() );
|
||||
aError = buf;
|
||||
return -1;
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
aError = std::string( aInPath ) + ": error: " + std::string( ioe.Problem().ToUTF8() );
|
||||
return -1;
|
||||
}
|
||||
catch( const std::exception& e )
|
||||
{
|
||||
aError = std::string( aInPath ) + ": error: " + e.what();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Footprint resave for --resave (kicad-validity 0001 S): parse + rewrite one
|
||||
// .kicad_mod in the current format, the exact FP_CACHE::Save incantation
|
||||
// (PRETTIFIED formatter + plugin Format). 0 / 4 load failed / 5 write failed.
|
||||
int pcbToolsResaveFootprint( const char* aInPath, const char* aOutPath, std::string& aError )
|
||||
{
|
||||
wxFileName fn( wxString::FromUTF8( aInPath ) );
|
||||
fn.MakeAbsolute();
|
||||
|
||||
kiRuntime();
|
||||
|
||||
std::unique_ptr<FOOTPRINT> fp;
|
||||
|
||||
try
|
||||
{
|
||||
PCB_IO_KICAD_SEXPR plugin;
|
||||
wxString name;
|
||||
fp.reset( plugin.ImportFootprint( fn.GetFullPath(), name ) );
|
||||
|
||||
if( !fp )
|
||||
{
|
||||
aError = std::string( aInPath ) + ": error: not a footprint file";
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
catch( PARSE_ERROR& pe )
|
||||
{
|
||||
char buf[1024];
|
||||
std::snprintf( buf, sizeof( buf ), "%s:%d:%d: error: %s", aInPath, pe.lineNumber,
|
||||
pe.byteIndex, (const char*) pe.ParseProblem().ToUTF8() );
|
||||
aError = buf;
|
||||
return 4;
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
aError = std::string( aInPath ) + ": error: " + std::string( ioe.Problem().ToUTF8() );
|
||||
return 4;
|
||||
}
|
||||
catch( const std::exception& e )
|
||||
{
|
||||
aError = std::string( aInPath ) + ": error: " + e.what();
|
||||
return 4;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// CTL_FOR_LIBRARY, NOT the default CTL_FOR_BOARD — the board flags
|
||||
// include CTL_OMIT_FOOTPRINT_VERSION, which would strip the (version)
|
||||
// header a standalone .kicad_mod must carry (FootprintSave sets the
|
||||
// same flags before formatting).
|
||||
PCB_IO_KICAD_SEXPR writer( CTL_FOR_LIBRARY );
|
||||
PRETTIFIED_FILE_OUTPUTFORMATTER formatter( wxString::FromUTF8( aOutPath ) );
|
||||
writer.SetOutputFormatter( &formatter );
|
||||
writer.Format( fp.get() );
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
aError = std::string( aOutPath ) + ": error: " + std::string( ioe.Problem().ToUTF8() );
|
||||
return 5;
|
||||
}
|
||||
catch( const std::exception& e )
|
||||
{
|
||||
aError = std::string( aOutPath ) + ": error: " + e.what();
|
||||
return 5;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Full-parse board resave for the merged image's --resave driver (also on the
|
||||
// eeschema side): a bare load like pcbToolsLintBoard, then the s-expr writer
|
||||
// rewrites the board in the current format version. Zones are written
|
||||
|
|
|
|||
|
|
@ -102,6 +102,10 @@ int pcbToolsLintBoard( const char* aInPath, std::string& aError );
|
|||
// Merged image only: board load + s-expr rewrite for --resave (kicad-validity
|
||||
// 0001). 0 resaved / 4 load failed / 5 write failed.
|
||||
int pcbToolsResaveBoard( const char* aInPath, const char* aOutPath, std::string& aError );
|
||||
// Merged image only: .kicad_mod full parse (returns pad count or -1) and
|
||||
// resave (0/4/5) — kicad-validity 0001 S.
|
||||
int pcbToolsLintFootprint( const char* aInPath, std::string& aError );
|
||||
int pcbToolsResaveFootprint( const char* aInPath, const char* aOutPath, std::string& aError );
|
||||
#endif
|
||||
|
||||
#include <connection_graph.h>
|
||||
|
|
@ -539,6 +543,15 @@ bool lintOneFile( const char* aPath, bool aStrict )
|
|||
else
|
||||
tier = "full parse";
|
||||
}
|
||||
else if( ext == wxS( "kicad_mod" ) )
|
||||
{
|
||||
std::string fpError;
|
||||
|
||||
if( pcbToolsLintFootprint( aPath, fpError ) < 0 )
|
||||
report.errors.push_back( fpError );
|
||||
else
|
||||
tier = "full parse";
|
||||
}
|
||||
#endif
|
||||
// Anything else (kicad_wks, kicad_pro …— and kicad_pcb outside
|
||||
// the merged kicad_tools image) stays structure-only.
|
||||
|
|
@ -813,12 +826,14 @@ int runResave( const char* aInPath, const char* aOutDir )
|
|||
return 0;
|
||||
}
|
||||
|
||||
if( ext == wxS( "kicad_pcb" ) )
|
||||
if( ext == wxS( "kicad_pcb" ) || ext == wxS( "kicad_mod" ) )
|
||||
{
|
||||
#ifdef KICAD_TOOLS_COMBINED
|
||||
const wxString outPath = outDir + inFn.GetFullName();
|
||||
std::string error;
|
||||
const int rc = pcbToolsResaveBoard( aInPath, (const char*) outPath.ToUTF8(), error );
|
||||
const int rc = ext == wxS( "kicad_pcb" )
|
||||
? pcbToolsResaveBoard( aInPath, (const char*) outPath.ToUTF8(), error )
|
||||
: pcbToolsResaveFootprint( aInPath, (const char*) outPath.ToUTF8(), error );
|
||||
|
||||
if( rc != 0 )
|
||||
std::fprintf( stderr, "%s\n", error.c_str() );
|
||||
|
|
@ -828,7 +843,8 @@ int runResave( const char* aInPath, const char* aOutDir )
|
|||
|
||||
return rc;
|
||||
#else
|
||||
std::fprintf( stderr, "%s: error: board resave requires the merged kicad_tools build\n",
|
||||
std::fprintf( stderr, "%s: error: board/footprint resave requires the merged "
|
||||
"kicad_tools build\n",
|
||||
aInPath );
|
||||
return 2;
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in a new issue