KiCad PCB EDA Suite
Loading...
Searching...
No Matches
symbol_import_reconciler.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
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU 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
21
22#include <map>
23#include <set>
24#include <utility>
25
26#include <wx/filefn.h>
27#include <wx/filename.h>
28
30#include <lib_id.h>
31#include <lib_symbol.h>
32#include <project.h>
33#include <project_sch.h>
34#include <reporter.h>
35#include <schematic.h>
36#include <sch_pin.h>
37#include <sch_screen.h>
38#include <sch_symbol.h>
40#include <io/io_mgr.h>
41#include <sch_io/sch_io.h>
42#include <sch_io/sch_io_mgr.h>
46
47
49 const wxString& aProjectPath,
50 REPORTER& aReporter ) :
51 m_adapter( aAdapter ),
52 m_projectPath( aProjectPath ),
53 m_reporter( aReporter )
54{
55}
56
57
58namespace
59{
60// every screen once, so a sheet instantiated many times does not re-walk its symbols
61std::vector<SCH_SYMBOL*> placedSymbols( SCHEMATIC* aSchematic )
62{
63 std::vector<SCH_SYMBOL*> symbols;
64 SCH_SCREENS screens( aSchematic->Root() );
65
66 for( SCH_SCREEN* screen = screens.GetFirst(); screen; screen = screens.GetNext() )
67 {
68 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
69 symbols.push_back( static_cast<SCH_SYMBOL*>( item ) );
70 }
71
72 return symbols;
73}
74
75
76// structural signature, flags same-name placed instances that differ
77wxString placedSignature( const SCH_SYMBOL* aSymbol )
78{
79 const std::unique_ptr<LIB_SYMBOL>& part = aSymbol->GetLibSymbolRef();
80
81 if( !part )
82 return wxEmptyString;
83
84 return wxString::Format( wxS( "%d:%d" ), part->GetPinCount(), part->GetUnitCount() );
85}
86
87
88// lookup that tolerates an unreadable or absent library
89LIB_SYMBOL* loadSymbol( SYMBOL_LIBRARY_ADAPTER& aAdapter, const wxString& aNickname,
90 const wxString& aName )
91{
92 try
93 {
94 return aAdapter.LoadSymbol( aNickname, aName );
95 }
96 catch( const IO_ERROR& )
97 {
98 return nullptr;
99 }
100}
101
102
103std::multiset<wxString> pinNumbers( const LIB_SYMBOL& aSymbol )
104{
105 std::multiset<wxString> numbers;
106
107 for( const SCH_PIN* pin : aSymbol.GetGraphicalPins( ALL_UNITS, ALL_BODY_STYLES ) )
108 numbers.insert( pin->GetNumber() );
109
110 return numbers;
111}
112
113
114// two tools never draw a part identically, so equivalence is the electrical interface
115bool sameInterface( const LIB_SYMBOL& aLhs, const LIB_SYMBOL& aRhs )
116{
117 return aLhs.GetUnitCount() == aRhs.GetUnitCount() && pinNumbers( aLhs ) == pinNumbers( aRhs );
118}
119
120
121// reuse existing row/file only if prior import-managed cache
122bool isManagedCache( const LIBRARY_TABLE_ROW* aRow )
123{
124 return aRow && aRow->GetOptionsMap().count( IMPORT_PROJ_PROPS::MANAGED_CACHE_KEY ) > 0;
125}
126}
127
128
131 std::vector<std::unique_ptr<LIB_SYMBOL>> aDefinitions,
132 const wxString& aCacheNickname,
133 const std::vector<wxString>& aSourceLibNicknames )
134{
136
137 if( !aSchematic )
138 return result;
139
140 // source nickname + item name, so same-name parts from different libraries stay split
141 using SOURCE_KEY = std::pair<wxString, wxString>;
142
143 std::map<SOURCE_KEY, LIB_SYMBOL*> defByKey;
144 std::map<wxString, std::vector<LIB_SYMBOL*>> defsByName;
145
146 for( const std::unique_ptr<LIB_SYMBOL>& def : aDefinitions )
147 {
148 wxString name = def->GetLibId().GetUniStringLibItemName();
149
150 if( name.IsEmpty() )
151 name = def->GetName();
152
153 if( name.IsEmpty() )
154 continue;
155
156 defByKey.emplace( SOURCE_KEY( def->GetLibId().GetUniStringLibNickname(), name ), def.get() );
157 defsByName[name].push_back( def.get() );
158 }
159
160 // definitions can carry a different nickname from the placed symbols, so a unique name still
161 // matches, but an ambiguous one must not
162 auto findDef = [&]( const wxString& aNick, const wxString& aName ) -> LIB_SYMBOL*
163 {
164 if( auto it = defByKey.find( SOURCE_KEY( aNick, aName ) ); it != defByKey.end() )
165 return it->second;
166
167 auto byName = defsByName.find( aName );
168
169 if( byName == defsByName.end() || byName->second.size() != 1 )
170 return nullptr;
171
172 return byName->second.front();
173 };
174
175 // preload source libs before membership queries
176 for( const wxString& nick : aSourceLibNicknames )
177 {
178 if( m_adapter.GetRow( nick ) )
179 m_adapter.LoadOne( nick );
180 }
181
182 std::set<wxString> provenance( aSourceLibNicknames.begin(), aSourceLibNicknames.end() );
183
184 // resolve one source lib, empty if none or ambiguous
185 auto resolveSource = [&]( const SCH_SYMBOL* aSymbol, const wxString& aName ) -> wxString
186 {
187 std::vector<wxString> candidates;
188 wxString ownNick = aSymbol->GetLibId().GetUniStringLibNickname();
189
190 if( !ownNick.IsEmpty() )
191 candidates.push_back( ownNick );
192
193 for( const wxString& nick : aSourceLibNicknames )
194 {
195 if( nick != ownNick )
196 candidates.push_back( nick );
197 }
198
199 std::vector<wxString> matches;
200
201 for( const wxString& nick : candidates )
202 {
203 if( !m_adapter.GetRow( nick ) )
204 continue;
205
206 LIB_SYMBOL* candidate = loadSymbol( m_adapter, nick, aName );
207
208 if( !candidate )
209 continue;
210
211 // A nickname the importer emitted is not provenance. An unrelated library that
212 // happens to carry the name must not swallow the imported definition, so it takes the
213 // link only when it holds the same part.
214 if( !provenance.count( nick ) )
215 {
216 LIB_SYMBOL* def = findDef( ownNick, aName );
217
218 // importers that retain no definitions leave the placed copy to match against
219 if( !def )
220 def = aSymbol->GetLibSymbolRef().get();
221
222 if( !def || !sameInterface( *candidate, *def ) )
223 continue;
224 }
225
226 matches.push_back( nick );
227 }
228
229 return matches.size() == 1 ? matches.front() : wxString( wxEmptyString );
230 };
231
232 std::vector<SCH_SYMBOL*> symbols = placedSymbols( aSchematic );
233
234 // per-instance target, empty target = cache-bound
235 std::map<SOURCE_KEY, wxString> targetByKey;
236 std::set<SOURCE_KEY> cacheKeys;
237 std::map<SOURCE_KEY, std::vector<SCH_SYMBOL*>> instancesByKey;
238
239 for( SCH_SYMBOL* symbol : symbols )
240 {
241 wxString name = symbol->GetLibId().GetUniStringLibItemName();
242
243 if( name.IsEmpty() )
244 continue;
245
246 SOURCE_KEY key( symbol->GetLibId().GetUniStringLibNickname(), name );
247
248 instancesByKey[key].push_back( symbol );
249
250 if( targetByKey.count( key ) )
251 continue;
252
253 wxString sourceNick = resolveSource( symbol, name );
254 targetByKey[key] = sourceNick;
255
256 if( sourceNick.IsEmpty() )
257 cacheKeys.insert( key );
258 }
259
260 // one library cannot hold two items of the same name, so a collision takes a suffix
261 std::set<wxString> takenNames;
262
263 auto uniqueName = [&takenNames]( const wxString& aName )
264 {
265 // importers pass names a library cannot hold, such as ones with '<'
266 wxString legalName = LIB_ID::FixIllegalChars( aName, false ).wx_str();
267 wxString candidate = legalName;
268
269 for( int suffix = 1; !takenNames.insert( candidate ).second; ++suffix )
270 candidate = wxString::Format( wxS( "%s_%d" ), legalName, suffix );
271
272 return candidate;
273 };
274
275 // canonical def per cache key, fall back to the placed instance cache if importer gave none
276 std::map<wxString, LIB_SYMBOL*> cacheDefs;
277 std::map<SOURCE_KEY, wxString> cacheNameByKey;
278 std::map<const LIB_SYMBOL*, wxString> cacheNameByDef;
279 std::vector<std::unique_ptr<LIB_SYMBOL>> placedDefs;
280 std::vector<wxString> renameReports;
281
282 // a derived symbol extends its parent by name, which a rename can move
283 std::vector<std::pair<LIB_SYMBOL*, SOURCE_KEY>> parentFixups;
284
285 for( const SOURCE_KEY& key : cacheKeys )
286 {
287 const wxString& name = key.second;
288 LIB_SYMBOL* def = findDef( key.first, name );
289
290 if( !def )
291 {
292 const std::vector<SCH_SYMBOL*>& instances = instancesByKey[key];
293
294 if( instances.empty() || !instances.front()->GetLibSymbolRef() )
295 continue;
296
297 wxString firstSig = placedSignature( instances.front() );
298
299 for( auto it = instances.begin() + 1; it != instances.end(); ++it )
300 {
301 if( placedSignature( *it ) != firstSig )
302 {
303 m_reporter.Report( wxString::Format( _( "Imported symbol '%s' has conflicting "
304 "placed definitions; keeping the "
305 "first." ), name ),
307 break;
308 }
309 }
310
311 placedDefs.push_back(
312 std::make_unique<LIB_SYMBOL>( *instances.front()->GetLibSymbolRef() ) );
313 def = placedDefs.back().get();
314 }
315
316 // one definition serving several source libraries stays a single cache item
317 if( auto it = cacheNameByDef.find( def ); it != cacheNameByDef.end() )
318 {
319 cacheNameByKey[key] = it->second;
320 continue;
321 }
322
323 wxString cacheName = uniqueName( name );
324
325 cacheNameByDef[def] = cacheName;
326 cacheNameByKey[key] = cacheName;
327 cacheDefs[cacheName] = def;
328
329 if( !def->GetParentName().IsEmpty() )
330 parentFixups.emplace_back( def, SOURCE_KEY( key.first, def->GetParentName() ) );
331
332 if( cacheName != name )
333 {
334 renameReports.push_back(
335 wxString::Format( _( "Imported symbol '%s' from '%s' was renamed to '%s' "
336 "in the import cache." ), name, key.first, cacheName ) );
337 }
338 }
339
340 for( const auto& [def, parentKey] : parentFixups )
341 {
342 if( auto it = cacheNameByKey.find( parentKey ); it != cacheNameByKey.end() )
343 def->SetParentName( it->second );
344 }
345
346 if( !cacheDefs.empty() )
347 writeAndRegisterCache( aCacheNickname, cacheDefs, result );
348
349 // no rename happened if the cache did not publish
350 if( !result.m_cacheNickname.IsEmpty() )
351 {
352 for( const wxString& report : renameReports )
353 m_reporter.Report( report, RPT_SEVERITY_WARNING );
354 }
355
356 // the screen caches each embedded copy under the id it was added with, so a new id needs a new entry
357 auto setLibId = []( SCH_SYMBOL* aSymbol, const LIB_ID& aLibId )
358 {
359 SCH_SCREEN* screen = dynamic_cast<SCH_SCREEN*>( aSymbol->GetParent() );
360 bool moved = screen && screen->Remove( aSymbol );
361
362 aSymbol->SetLibId( aLibId );
363
364 // the embedded copy names itself in the netlist's library parts, so it follows the new id
365 if( aSymbol->UseLibIdLookup() && aSymbol->GetLibSymbolRef() )
366 {
367 aSymbol->GetLibSymbolRef()->SetName( aLibId.GetUniStringLibItemName() );
368 aSymbol->GetLibSymbolRef()->SetLibId( aLibId );
369 }
370
371 if( moved )
372 screen->Append( aSymbol );
373 };
374
375 // re-point nicks to the resolved lib, cache-bound symbols also take their cache item name
376 for( SCH_SYMBOL* symbol : symbols )
377 {
378 LIB_ID libId = symbol->GetLibId();
379 wxString name = libId.GetUniStringLibItemName();
380
381 if( name.IsEmpty() )
382 continue;
383
384 SOURCE_KEY key( libId.GetUniStringLibNickname(), name );
385 auto it = targetByKey.find( key );
386
387 if( it == targetByKey.end() )
388 {
389 result.m_unresolved++;
390 continue;
391 }
392
393 // empty resolution = cache-bound, resolves only once the cache is published
394 if( it->second.IsEmpty() )
395 {
396 auto cacheName = cacheNameByKey.find( key );
397
398 if( result.m_cacheNickname.IsEmpty() || cacheName == cacheNameByKey.end() )
399 {
400 result.m_unresolved++;
401 continue;
402 }
403
404 libId.SetLibNickname( aCacheNickname );
405 libId.SetLibItemName( cacheName->second );
406 setLibId( symbol, libId );
407 result.m_linkedToCache++;
408 }
409 else
410 {
411 libId.SetLibNickname( it->second );
412 setLibId( symbol, libId );
413 result.m_linkedToSource++;
414 }
415 }
416
417 return result;
418}
419
420
422 const wxString& aCacheNickname, const std::map<wxString, LIB_SYMBOL*>& aCacheDefs,
424{
425 wxFileName finalFn( m_projectPath, aCacheNickname, FILEEXT::KiCadSymbolLibFileExtension );
426 wxString finalPath = finalFn.GetFullPath();
427 wxString tempPath = finalPath + wxS( ".tmp" );
428
429 // a nickname the user already owns is never repurposed, whatever its row points at
430 LIBRARY_TABLE_ROW* existingRow = m_adapter.GetRow( aCacheNickname ).value_or( nullptr );
431
432 if( existingRow && !isManagedCache( existingRow ) )
433 {
434 m_reporter.Report( wxString::Format( _( "A symbol library named '%s' is already "
435 "registered; leaving imported symbols "
436 "unresolved." ), aCacheNickname ),
438 return;
439 }
440
441 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_KICAD ) );
442
443 if( !pi )
444 {
445 m_reporter.Report( _( "Cannot reconcile imported symbols: no KiCad symbol writer." ),
447 return;
448 }
449
450 // best-effort cleanup, must not throw
451 auto safeDelete = [&pi]( const wxString& aPath )
452 {
453 try
454 {
455 pi->DeleteLibrary( aPath );
456 }
457 catch( const IO_ERROR& )
458 {
459 }
460 };
461
462 bool wrote = false;
463
464 try
465 {
466 if( wxFileExists( tempPath ) )
467 pi->DeleteLibrary( tempPath );
468
469 pi->CreateLibrary( tempPath );
470
471 // buffer the writes, the library is flushed once by SaveLibrary
472 std::map<std::string, UTF8> properties;
473 properties.emplace( SCH_IO_KICAD_SEXPR::PropBuffering, wxEmptyString );
474
475 for( const auto& [name, def] : aCacheDefs )
476 {
477 std::unique_ptr<LIB_SYMBOL> copy = std::make_unique<LIB_SYMBOL>( *def );
478
479 // the library is keyed by the symbol name, which SetLibId leaves alone
480 copy->SetName( name );
481
482 LIB_ID id = copy->GetLibId();
483
484 id.SetLibNickname( aCacheNickname );
485 copy->SetLibId( id );
486 pi->SaveSymbol( tempPath, std::move( copy ), &properties );
487 }
488
489 pi->SaveLibrary( tempPath );
490 wrote = true;
491 }
492 catch( const IO_ERROR& ioe )
493 {
494 m_reporter.Report( wxString::Format( _( "Error writing imported symbol cache '%s': %s" ),
495 aCacheNickname, ioe.What() ),
497 }
498
499 if( !wrote )
500 {
501 if( wxFileExists( tempPath ) )
502 safeDelete( tempPath );
503
504 return;
505 }
506
507 // publish temp->final, replace only a managed cache, never a user lib
508 if( wxFileExists( finalPath ) )
509 {
510 if( isManagedCache( existingRow ) )
511 {
512 safeDelete( finalPath );
513 }
514 else
515 {
516 m_reporter.Report( wxString::Format( _( "A library already exists at '%s'; leaving "
517 "imported symbols unresolved." ), finalPath ),
519 safeDelete( tempPath );
520 return;
521 }
522 }
523
524 if( !wxRenameFile( tempPath, finalPath, false ) )
525 {
526 m_reporter.Report( wxString::Format( _( "Could not publish imported symbol cache to "
527 "'%s'." ), finalPath ),
529 safeDelete( tempPath );
530 return;
531 }
532
533 // only claim the cache when its table row is registered, else LIB_IDs re-point to a dead nickname
534 if( !registerCacheRow( aCacheNickname ) )
535 return;
536
537 aResult.m_cacheNickname = aCacheNickname;
538 aResult.m_savedToCache = static_cast<int>( aCacheDefs.size() );
539}
540
541
542bool SYMBOL_IMPORT_RECONCILER::registerCacheRow( const wxString& aCacheNickname )
543{
544 std::optional<LIBRARY_TABLE*> tableOpt = m_adapter.ProjectTable();
545
546 if( !tableOpt || !*tableOpt )
547 {
548 m_reporter.Report( _( "Cannot register imported symbol cache: no project library "
549 "table." ), RPT_SEVERITY_ERROR );
550 return false;
551 }
552
553 LIBRARY_TABLE* table = *tableOpt;
554 wxString cacheFile = aCacheNickname + wxS( "." )
556 wxString uri = wxS( "${KIPRJMOD}/" ) + cacheFile;
557 LIBRARY_TABLE_ROW* row = table->HasRow( aCacheNickname )
558 ? table->Row( aCacheNickname ).value_or( nullptr )
559 : &table->InsertRow();
560
561 if( !row )
562 return false;
563
564 row->SetNickname( aCacheNickname );
565 row->SetURI( uri );
566 row->SetType( wxS( "KiCad" ) );
569
570 // an unsaved row is gone on restart, so the cache cannot be claimed
571 if( !table->Save() )
572 {
573 m_reporter.Report( _( "Error saving project symbol library table; imported symbols left "
574 "unresolved." ), RPT_SEVERITY_ERROR );
575 return false;
576 }
577
578 // load the cache so membership and later lookups resolve it
579 m_adapter.LoadOne( aCacheNickname );
580 return true;
581}
582
583
585ReconcileImportedSymbols( SCH_IO& aPlugin, SCHEMATIC& aSchematic, PROJECT& aProject,
586 const wxString& aSchematicPath,
587 const std::map<std::string, UTF8>* aProperties, REPORTER& aReporter )
588{
590 std::vector<std::unique_ptr<LIB_SYMBOL>> definitions;
591
592 try
593 {
594 for( LIB_SYMBOL* symbol : aPlugin.GetImportedCachedLibrarySymbols() )
595 definitions.emplace_back( symbol );
596 }
597 catch( const IO_ERROR& )
598 {
599 // importer retains no definitions, the placed symbols are the fallback
600 }
601
603
604 if( !adapter )
605 return result;
606
607 // manager pre-commits the cache nickname + source libs; standalone import derives from filename
608 wxString cacheNick;
609 std::vector<wxString> sourceLibs;
610 IMPORT_PROJ_PROPS::ReadSymbolProps( aProperties, cacheNick, sourceLibs );
611
612 if( cacheNick.IsEmpty() )
613 {
615 wxFileName( aSchematicPath ).GetName() );
616 }
617
618 SYMBOL_IMPORT_RECONCILER reconciler( *adapter, aProject.GetProjectPath(), aReporter );
619
620 // reconciliation failure must not abort the import
621 try
622 {
623 result = reconciler.Reconcile( &aSchematic, std::move( definitions ), cacheNick,
624 sourceLibs );
625 }
626 catch( const IO_ERROR& ioe )
627 {
628 aReporter.Report( wxString::Format( _( "Could not reconcile imported symbol libraries: "
629 "%s" ), ioe.What() ), RPT_SEVERITY_ERROR );
630 }
631
632 return result;
633}
const char * name
EDA_ITEM * GetParent() const
Definition eda_item.h:112
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
void SetOptions(const wxString &aOptions)
void SetNickname(const wxString &aNickname)
void SetType(const wxString &aType)
std::map< std::string, UTF8 > GetOptionsMap() const
void SetURI(const wxString &aUri)
void SetScope(LIBRARY_TABLE_SCOPE aScope)
A logical library item identifier and consists of various portions much like a URI.
Definition lib_id.h:45
int SetLibItemName(const UTF8 &aLibItemName)
Override the library item name portion of the LIB_ID to aLibItemName.
Definition lib_id.cpp:124
int SetLibNickname(const UTF8 &aLibNickname)
Override the logical library name portion of the LIB_ID to aLibNickname.
Definition lib_id.cpp:113
const wxString GetUniStringLibItemName() const
Get strings for display messages in dialogs.
Definition lib_id.h:108
const wxString GetUniStringLibNickname() const
Definition lib_id.h:84
static UTF8 FixIllegalChars(const UTF8 &aLibItemName, bool aLib)
Replace illegal LIB_ID item name characters with underscores '_'.
Definition lib_id.cpp:205
Define a library symbol object.
Definition lib_symbol.h:114
const wxString & GetParentName() const
Definition lib_symbol.h:995
int GetUnitCount() const override
void SetLibId(const LIB_ID &aLibId)
std::vector< SCH_PIN * > GetGraphicalPins(int aUnit=0, int aBodyStyle=0) const override
Graphical pins: Return schematic pin objects as drawn (unexpanded), filtered by unit/body.
virtual void SetName(const wxString &aName)
static SYMBOL_LIBRARY_ADAPTER * SymbolLibAdapter(PROJECT *aProject)
Accessor for project symbol library manager adapter.
Container for project specific data.
Definition project.h:63
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition project.cpp:276
A pure virtual class used to derive REPORTER objects from.
Definition reporter.h:73
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Report a string with a given severity.
Definition reporter.h:102
Holds all the data relating to one schematic.
Definition schematic.h:149
SCH_SHEET & Root() const
Definition schematic.h:208
static const char * PropBuffering
The property used internally by the plugin to enable cache buffering which prevents the library file ...
Base class that schematic file and library loading and saving plugins should derive from.
Definition sch_io.h:60
virtual std::vector< LIB_SYMBOL * > GetImportedCachedLibrarySymbols()
Return the canonical symbol definitions produced by the last LoadSchematicFile().
Definition sch_io.cpp:76
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:170
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition sch_screen.h:826
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
bool Remove(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Remove aItem from the schematic associated with this screen.
Schematic symbol object.
Definition sch_symbol.h:75
void SetLibId(const LIB_ID &aName)
bool UseLibIdLookup() const
Definition sch_symbol.h:182
const LIB_ID & GetLibId() const override
Definition sch_symbol.h:165
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition sch_symbol.h:184
Frame-independent, non-interactive service that reconciles the symbol-library references of a freshly...
bool registerCacheRow(const wxString &aCacheNickname)
Insert or refresh the project symbol-library-table row for the generated cache.
SYMBOL_IMPORT_RECONCILER(SYMBOL_LIBRARY_ADAPTER &aAdapter, const wxString &aProjectPath, REPORTER &aReporter=NULL_REPORTER::GetInstance())
SYMBOL_IMPORT_RECONCILE_RESULT Reconcile(SCHEMATIC *aSchematic, std::vector< std::unique_ptr< LIB_SYMBOL > > aDefinitions, const wxString &aCacheNickname, const std::vector< wxString > &aSourceLibNicknames)
Reconcile aSchematic against the importer definitions and the provenance source libraries.
SYMBOL_LIBRARY_ADAPTER & m_adapter
void writeAndRegisterCache(const wxString &aCacheNickname, const std::map< wxString, LIB_SYMBOL * > &aCacheDefs, SYMBOL_IMPORT_RECONCILE_RESULT &aResult)
Write the residual definitions into an atomically-published .kicad_sym and register its row.
An interface to the global shared library manager that is schematic-specific and linked to one projec...
LIB_SYMBOL * LoadSymbol(const wxString &aNickname, const wxString &aName)
Load a LIB_SYMBOL having aName from the library given by aNickname.
wxString wx_str() const
Definition utf8.cpp:41
#define _(s)
static const std::string KiCadSymbolLibFileExtension
std::unique_ptr< T > IO_RELEASER
Helper to hold and release an IO_BASE object when exceptions are thrown.
Definition io_mgr.h:33
void ReadSymbolProps(const std::map< std::string, UTF8 > *aProps, wxString &aCacheNickname, std::vector< wxString > &aSourceSymLibs)
Read the symbol-import coordination properties out of a properties map.
wxString ManagedCacheOption()
Options string identifying a library-table row as a generated import cache.
constexpr char MANAGED_CACHE_KEY[]
Library-table row option key marking a row as a generated import cache.
wxString MakeSymbolCacheNickname(const wxString &aStem)
Derive the generated symbol-cache nickname from a project or file stem.
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_ERROR
LIB_SYMBOL * loadSymbol(const wxString &aLibraryPath, nlohmann::json aFileData, const wxString &aAliasName, const std::map< std::string, UTF8 > *aProperties)
Outcome of a post-import symbol-library reconciliation pass.
wxString m_cacheNickname
nickname of the generated cache, empty if none written
int m_savedToCache
distinct definitions written into the cache library
#define ALL_UNITS
Definition symbol.h:150
#define ALL_BODY_STYLES
Definition symbol.h:151
SYMBOL_IMPORT_RECONCILE_RESULT ReconcileImportedSymbols(SCH_IO &aPlugin, SCHEMATIC &aSchematic, PROJECT &aProject, const wxString &aSchematicPath, const std::map< std::string, UTF8 > *aProperties, REPORTER &aReporter)
Reconcile aSchematic against the definitions aPlugin retained while loading it.
bool moved
KIBIS_PIN * pin
static std::vector< int > candidates(const SEGMENT_INDEX &aIndex, const SEG &aQuery, int aPadding)
wxString result
Test unit parsing edge cases and error handling.
@ SCH_SYMBOL_T
Definition typeinfo.h:168
Definition of file extensions used in Kicad.