KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_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
20#include <memory>
21#include <vector>
22
23#include <qa_utils/file_utils.h>
25
26#include <wx/dir.h>
27#include <wx/file.h>
28#include <wx/filefn.h>
29#include <wx/filename.h>
30
31#include <lib_id.h>
32#include <lib_symbol.h>
33#include <pgm_base.h>
34#include <project.h>
35#include <project_sch.h>
36#include <reporter.h>
37#include <schematic.h>
38#include <sch_io/sch_io.h>
39#include <sch_io/sch_io_mgr.h>
40#include <sch_screen.h>
41#include <sch_sheet.h>
42#include <sch_sheet_path.h>
43#include <sch_symbol.h>
49
51
52
53namespace
54{
56struct STAGED_PROJECT_FIXTURE
57{
58 STAGED_PROJECT_FIXTURE() :
59 m_staged( Pgm().GetSettingsManager(), wxS( "symreconcile-qa" ), wxS( "symreconcile" ) )
60 {
61 Pgm().GetLibraryManager().LoadProjectTables( m_staged.Project().GetProjectDirectory() );
62 }
63
64 KI_TEST::SCOPED_TEMP_PROJECT m_staged;
65};
66
67
68wxString easyEdaProV3Archive()
69{
70 return wxString::FromUTF8( KI_TEST::GetTestDataRootDir()
71 + "pcbnew/plugins/easyedapro/ProProject_LS2K0300Core_2025-11-14.epro2" );
72}
73
74
76bool hasSymbolLib( const wxString& aPath )
77{
78 wxDir dir( aPath );
79 wxString name;
80
81 if( !dir.IsOpened() )
82 return false;
83
84 wxString spec = wxS( "*." ) + wxString( FILEEXT::KiCadSymbolLibFileExtension );
85
86 return dir.GetFirst( &name, spec, wxDIR_FILES );
87}
88
89
91struct IMPORTED_SAMPLE
92{
93 IO_RELEASER<SCH_IO> m_plugin;
94 std::unique_ptr<SCHEMATIC> m_schematic;
95 std::vector<std::unique_ptr<LIB_SYMBOL>> m_definitions;
96 wxString m_sourceDir;
97};
98
99
100IMPORTED_SAMPLE importSample( PROJECT& aProject )
101{
102 IMPORTED_SAMPLE sample;
103
104 wxString sep = wxFileName::GetPathSeparator();
105 sample.m_sourceDir = aProject.GetProjectPath() + wxT( "import-src" );
106 BOOST_REQUIRE( wxFileName::Mkdir( sample.m_sourceDir, wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL ) );
107
108 wxFileName archiveFile( sample.m_sourceDir + sep, wxS( "sample" ), wxS( "epro2" ) );
109 BOOST_REQUIRE( wxCopyFile( easyEdaProV3Archive(), archiveFile.GetFullPath() ) );
110
111 sample.m_schematic = std::make_unique<SCHEMATIC>( nullptr );
112 sample.m_schematic->SetProject( &aProject );
113
114 sample.m_plugin.reset( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_EASYEDAPRO_V3 ) );
115 BOOST_REQUIRE( sample.m_plugin );
116
117 SCH_SHEET* rootSheet = nullptr;
118 BOOST_REQUIRE_NO_THROW( rootSheet = sample.m_plugin->LoadSchematicFile(
119 archiveFile.GetFullPath(), sample.m_schematic.get() ) );
120 BOOST_REQUIRE( rootSheet );
121
122 sample.m_schematic->RefreshHierarchy();
123
124 for( LIB_SYMBOL* symbol : sample.m_plugin->GetImportedCachedLibrarySymbols() )
125 sample.m_definitions.emplace_back( symbol );
126
127 BOOST_REQUIRE_GT( sample.m_definitions.size(), 0 );
128
129 return sample;
130}
131
132
133std::vector<SCH_SYMBOL*> placedSymbols( SCHEMATIC& aSchematic )
134{
135 std::vector<SCH_SYMBOL*> symbols;
136
137 for( const SCH_SHEET_PATH& sheetPath : aSchematic.Hierarchy() )
138 {
139 if( SCH_SCREEN* screen = sheetPath.LastScreen() )
140 {
141 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
142 symbols.push_back( static_cast<SCH_SYMBOL*>( item ) );
143 }
144 }
145
146 return symbols;
147}
148
149
151void publishLibrary( PROJECT& aProject, SYMBOL_LIBRARY_ADAPTER& aAdapter, const wxString& aNickname,
152 const wxString& aFileStem, const LIB_SYMBOL& aSymbol )
153{
154 wxFileName libFn( aProject.GetProjectPath(), aFileStem, FILEEXT::KiCadSymbolLibFileExtension );
155
156 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_KICAD ) );
157 BOOST_REQUIRE( pi );
158
159 pi->CreateLibrary( libFn.GetFullPath() );
160
161 auto copy = std::make_unique<LIB_SYMBOL>( aSymbol );
162 copy->SetLibId( LIB_ID( aNickname, copy->GetName() ) );
163 pi->SaveSymbol( libFn.GetFullPath(), std::move( copy ) );
164
165 LIBRARY_TABLE* table = aAdapter.ProjectTable().value_or( nullptr );
167
168 LIBRARY_TABLE_ROW& row = table->InsertRow();
169 row.SetNickname( aNickname );
170 row.SetURI( wxS( "${KIPRJMOD}/" ) + libFn.GetFullName() );
171 row.SetType( wxS( "KiCad" ) );
173
174 BOOST_REQUIRE( table->Save().has_value() );
175 aAdapter.LoadOne( aNickname );
176}
177
178
180struct COLLISION_CANDIDATE
181{
182 SCH_SYMBOL* m_symbol = nullptr;
183 LIB_SYMBOL* m_definition = nullptr;
184 wxString m_nickname;
185 wxString m_name;
186};
187
188
189COLLISION_CANDIDATE findCandidate( IMPORTED_SAMPLE& aSample )
190{
191 COLLISION_CANDIDATE candidate;
192
193 for( SCH_SYMBOL* symbol : placedSymbols( *aSample.m_schematic ) )
194 {
195 wxString nick = symbol->GetLibId().GetUniStringLibNickname();
196 wxString name = symbol->GetLibId().GetUniStringLibItemName();
197
198 if( nick.IsEmpty() || name.IsEmpty() )
199 continue;
200
201 for( const std::unique_ptr<LIB_SYMBOL>& def : aSample.m_definitions )
202 {
203 if( def->GetLibId().GetUniStringLibItemName() != name || def->GetPins().empty() )
204 continue;
205
206 candidate.m_symbol = symbol;
207 candidate.m_definition = def.get();
208 candidate.m_nickname = nick;
209 candidate.m_name = name;
210
211 return candidate;
212 }
213 }
214
215 return candidate;
216}
217} // namespace
218
219
220BOOST_FIXTURE_TEST_SUITE( SymbolImportReconciler, STAGED_PROJECT_FIXTURE )
221
222
223// EasyEDA Pro v3 hands definitions over the standard hook, leaving the source directory untouched
224// fails on revert, since LoadSchematicFile then publishes its own .kicad_sym beside the archive
225BOOST_AUTO_TEST_CASE( EasyEdaProV3SchematicResolvesToGeneratedCache )
226{
227 PROJECT& project = m_staged.Project();
228
229 IMPORTED_SAMPLE sample = importSample( project );
230 SCHEMATIC& schematic = *sample.m_schematic;
231
232 // the importer must not have published anything of its own beside the archive
233 BOOST_CHECK_MESSAGE( !hasSymbolLib( sample.m_sourceDir ),
234 "LoadSchematicFile wrote a library into the source directory" );
235
237 BOOST_REQUIRE( adapter );
238
239 const wxString cacheNick = wxS( "ls2k0300-import-syms" );
240 SYMBOL_IMPORT_RECONCILER reconciler( *adapter, project.GetProjectPath() );
241
243 reconciler.Reconcile( &schematic, std::move( sample.m_definitions ), cacheNick, {} );
244
245 // the cache lands in the project directory, not next to the source archive
246 BOOST_CHECK_EQUAL( result.m_cacheNickname, cacheNick );
247 BOOST_CHECK_GT( result.m_savedToCache, 0 );
248
249 wxFileName cacheFile( project.GetProjectPath(), cacheNick,
251 BOOST_CHECK_MESSAGE( wxFileExists( cacheFile.GetFullPath() ),
252 "Generated .kicad_sym was not published into the project" );
253
254 LIBRARY_TABLE* projectTable = adapter->ProjectTable().value_or( nullptr );
255 BOOST_REQUIRE( projectTable );
256 BOOST_CHECK( projectTable->HasRow( cacheNick ) );
257
258 // every placed symbol resolves through the adapter after reconciliation
259 int resolved = 0;
260
261 for( const SCH_SHEET_PATH& sheetPath : schematic.Hierarchy() )
262 {
263 SCH_SCREEN* screen = sheetPath.LastScreen();
264
265 if( !screen )
266 continue;
267
268 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
269 {
270 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
271 wxString name = symbol->GetLibId().GetUniStringLibItemName();
272
273 if( name.IsEmpty() )
274 continue;
275
276 wxString nick = symbol->GetLibId().GetUniStringLibNickname();
277
278 BOOST_CHECK_MESSAGE( !nick.IsEmpty(),
279 wxString::Format( "Symbol '%s' left with empty nickname", name ) );
280 BOOST_CHECK_MESSAGE( adapter->LoadSymbol( nick, name ) != nullptr,
281 wxString::Format( "LIB_ID '%s:%s' does not resolve after "
282 "reconciliation", nick, name ) );
283 resolved++;
284 }
285 }
286
287 BOOST_CHECK_GT( resolved, 0 );
288 BOOST_CHECK_EQUAL( result.m_unresolved, 0 );
289}
290
291
292// EasyEDA Pro v2 wrote its .kicad_sym beside the source archive, exactly as v3 did
293BOOST_AUTO_TEST_CASE( EasyEdaProV2LeavesSourceDirectoryClean )
294{
295 PROJECT& project = m_staged.Project();
296
297 wxString sep = wxFileName::GetPathSeparator();
298 wxString srcDir = project.GetProjectPath() + wxT( "import-src" );
299 BOOST_REQUIRE( wxFileName::Mkdir( srcDir, wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL ) );
300
301 wxString source = wxString::FromUTF8(
303 + "pcbnew/plugins/easyedapro/ProProject_Yuzuki Chameleon_2023-09-02.epro" );
304 BOOST_REQUIRE( wxFileExists( source ) );
305
306 wxFileName archiveFile( srcDir + sep, wxS( "sample" ), wxS( "epro" ) );
307 BOOST_REQUIRE( wxCopyFile( source, archiveFile.GetFullPath() ) );
308
309 SCHEMATIC schematic( nullptr );
310 schematic.SetProject( &project );
311
312 IO_RELEASER<SCH_IO> plugin( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_EASYEDAPRO ) );
313 BOOST_REQUIRE( plugin );
314
315 SCH_SHEET* rootSheet = nullptr;
316 BOOST_REQUIRE_NO_THROW(
317 rootSheet = plugin->LoadSchematicFile( archiveFile.GetFullPath(), &schematic ) );
318 BOOST_REQUIRE( rootSheet );
319
320 BOOST_CHECK_MESSAGE( !hasSymbolLib( srcDir ),
321 "LoadSchematicFile wrote a library into the source directory" );
322
323 // the definitions still reach the reconciler through the standard hook
324 std::vector<LIB_SYMBOL*> raw = plugin->GetImportedCachedLibrarySymbols();
325 BOOST_CHECK_GT( raw.size(), 0 );
326
327 for( LIB_SYMBOL* symbol : raw )
328 delete symbol;
329}
330
331
332// An unrelated library that happens to carry the nickname the importer emitted must not swallow
333// the imported definition; without the provenance check the symbol relinks to the wrong part
334BOOST_AUTO_TEST_CASE( CollidingNicknameDoesNotStealTheLink )
335{
336 PROJECT& project = m_staged.Project();
337
338 IMPORTED_SAMPLE sample = importSample( project );
339 COLLISION_CANDIDATE candidate = findCandidate( sample );
340 BOOST_REQUIRE( candidate.m_symbol );
341
343 BOOST_REQUIRE( adapter );
344
345 // a pinless namesake registered under the importer's nickname: same name, different part
346 LIB_SYMBOL impostor( candidate.m_name );
347 BOOST_REQUIRE( impostor.GetPins().empty() );
348 publishLibrary( project, *adapter, candidate.m_nickname, wxS( "impostor" ), impostor );
349
350 const wxString cacheNick = wxS( "collide-import-syms" );
351 SYMBOL_IMPORT_RECONCILER reconciler( *adapter, project.GetProjectPath() );
352
354 sample.m_schematic.get(), std::move( sample.m_definitions ), cacheNick, {} );
355
356 BOOST_CHECK_EQUAL( result.m_cacheNickname, cacheNick );
357
358 // the imported definition is kept in the cache rather than dropped for the namesake
359 BOOST_CHECK_EQUAL( candidate.m_symbol->GetLibId().GetUniStringLibNickname(), cacheNick );
360
361 LIB_SYMBOL* linked = adapter->LoadSymbol( cacheNick, candidate.m_name );
362 BOOST_REQUIRE( linked );
363 BOOST_CHECK_GT( linked->GetPins().size(), 0 );
364}
365
366
367// The same nickname collision resolves the other way when the library really does hold the part,
368// so the equivalence escape hatch keeps a genuine match out of the generated cache
369BOOST_AUTO_TEST_CASE( EquivalentNamesakeTakesTheLink )
370{
371 PROJECT& project = m_staged.Project();
372
373 IMPORTED_SAMPLE sample = importSample( project );
374 COLLISION_CANDIDATE candidate = findCandidate( sample );
375 BOOST_REQUIRE( candidate.m_symbol );
376
378 BOOST_REQUIRE( adapter );
379
380 publishLibrary( project, *adapter, candidate.m_nickname, wxS( "genuine" ),
381 *candidate.m_definition );
382
383 const wxString cacheNick = wxS( "equivalent-import-syms" );
384 wxString sourceNick = candidate.m_nickname;
385 SYMBOL_IMPORT_RECONCILER reconciler( *adapter, project.GetProjectPath() );
386
388 sample.m_schematic.get(), std::move( sample.m_definitions ), cacheNick, {} );
389
390 BOOST_CHECK_EQUAL( candidate.m_symbol->GetLibId().GetUniStringLibNickname(), sourceNick );
391 BOOST_CHECK_GT( result.m_linkedToSource, 0 );
392}
393
394
395// Two source libraries supplying different symbols under one bare name must both survive the
396// cache; keying the cache by the bare name alone dropped the second and relinked its instance
397BOOST_AUTO_TEST_CASE( SameNameFromDifferentLibrariesKeepsBothDefinitions )
398{
399 PROJECT& project = m_staged.Project();
400
401 IMPORTED_SAMPLE sample = importSample( project );
402
403 // two real imported symbols that a pin count tells apart
404 SCH_SYMBOL* firstPlaced = nullptr;
405 SCH_SYMBOL* secondPlaced = nullptr;
406
407 for( SCH_SYMBOL* symbol : placedSymbols( *sample.m_schematic ) )
408 {
409 const std::unique_ptr<LIB_SYMBOL>& part = symbol->GetLibSymbolRef();
410
411 if( !part || part->GetPins().empty() )
412 continue;
413
414 if( !firstPlaced )
415 firstPlaced = symbol;
416 else if( part->GetPins().size() != firstPlaced->GetLibSymbolRef()->GetPins().size() )
417 secondPlaced = symbol;
418
419 if( secondPlaced )
420 break;
421 }
422
423 BOOST_REQUIRE( firstPlaced );
424 BOOST_REQUIRE( secondPlaced );
425
426 const wxString sharedName = wxS( "SHARED_SYM" );
427 const size_t firstPins = firstPlaced->GetLibSymbolRef()->GetPins().size();
428 const size_t secondPins = secondPlaced->GetLibSymbolRef()->GetPins().size();
429
430 std::vector<std::unique_ptr<LIB_SYMBOL>> defs;
431
432 // the same bare name under two source libraries, both placed and defined
433 auto relabel = [&]( SCH_SYMBOL* aSymbol, const wxString& aNickname )
434 {
435 auto def = std::make_unique<LIB_SYMBOL>( *aSymbol->GetLibSymbolRef() );
436 def->SetName( sharedName );
437 def->SetLibId( LIB_ID( aNickname, sharedName ) );
438 defs.push_back( std::move( def ) );
439
440 aSymbol->SetLibId( LIB_ID( aNickname, sharedName ) );
441 };
442
443 relabel( firstPlaced, wxS( "libAlpha" ) );
444 relabel( secondPlaced, wxS( "libBeta" ) );
445
447 BOOST_REQUIRE( adapter );
448
449 const wxString cacheNick = wxS( "namecollide-import-syms" );
451 SYMBOL_IMPORT_RECONCILER reconciler( *adapter, project.GetProjectPath(), reporter );
452
454 reconciler.Reconcile( sample.m_schematic.get(), std::move( defs ), cacheNick, {} );
455
456 BOOST_CHECK_EQUAL( result.m_cacheNickname, cacheNick );
457
458 LIB_ID firstId = firstPlaced->GetLibId();
459 LIB_ID secondId = secondPlaced->GetLibId();
460
461 BOOST_CHECK_EQUAL( firstId.GetUniStringLibNickname(), cacheNick );
462 BOOST_CHECK_EQUAL( secondId.GetUniStringLibNickname(), cacheNick );
463 BOOST_CHECK_MESSAGE( firstId.GetUniStringLibItemName() != secondId.GetUniStringLibItemName(),
464 "Symbols from two source libraries share one cache item name" );
465
466 // each instance still resolves to the symbol it was imported as
467 LIB_SYMBOL* firstLinked = adapter->LoadSymbol( cacheNick, firstId.GetUniStringLibItemName() );
468 LIB_SYMBOL* secondLinked = adapter->LoadSymbol( cacheNick, secondId.GetUniStringLibItemName() );
469
470 BOOST_REQUIRE( firstLinked );
471 BOOST_REQUIRE( secondLinked );
472 BOOST_CHECK_EQUAL( firstLinked->GetPins().size(), firstPins );
473 BOOST_CHECK_EQUAL( secondLinked->GetPins().size(), secondPins );
474
475 // the user is told which symbol the cache renamed
476 const wxString renamed = firstId.GetUniStringLibItemName() == sharedName
477 ? secondId.GetUniStringLibItemName()
478 : firstId.GetUniStringLibItemName();
479
480 BOOST_CHECK_MESSAGE( reporter.GetMessages().Contains(
481 wxString::Format( wxS( "renamed to '%s'" ), renamed ) ),
482 "Cache rename was not reported" );
483}
484
485
486// A project row already owning the cache nickname is a user library even when no file sits at the
487// generated path, so publishing must not rewrite its URI
488BOOST_AUTO_TEST_CASE( ExistingUserRowIsNotRepurposed )
489{
490 PROJECT& project = m_staged.Project();
491
492 IMPORTED_SAMPLE sample = importSample( project );
493
495 BOOST_REQUIRE( adapter );
496
497 const wxString cacheNick = wxS( "row-import-syms" );
498
499 // the user's row owns the nickname but points at a file of its own
500 LIB_SYMBOL owned( wxS( "UserPart" ) );
501 publishLibrary( project, *adapter, cacheNick, wxS( "user-owned" ), owned );
502
503 LIBRARY_TABLE* table = adapter->ProjectTable().value_or( nullptr );
505
506 LIBRARY_TABLE_ROW* row = table->Row( cacheNick ).value_or( nullptr );
507 BOOST_REQUIRE( row );
508
509 const wxString uriBefore = row->URI();
510
511 SYMBOL_IMPORT_RECONCILER reconciler( *adapter, project.GetProjectPath() );
512
514 sample.m_schematic.get(), std::move( sample.m_definitions ), cacheNick, {} );
515
516 BOOST_CHECK( result.m_cacheNickname.IsEmpty() );
517 BOOST_CHECK_EQUAL( row->URI(), uriBefore );
518
519 wxFileName cacheFile( project.GetProjectPath(), cacheNick,
521 BOOST_CHECK_MESSAGE( !wxFileExists( cacheFile.GetFullPath() ),
522 "Published a cache over a nickname the user already owns" );
523}
524
525
526// A cache whose table row cannot be persisted is gone on restart, so it must not be claimed
527BOOST_AUTO_TEST_CASE( UnsavableTableLeavesCacheUnclaimed )
528{
529 PROJECT& project = m_staged.Project();
530
532 BOOST_REQUIRE( adapter );
533
534 LIBRARY_TABLE* table = adapter->ProjectTable().value_or( nullptr );
536 BOOST_REQUIRE( table->Save().has_value() );
537
538 wxFileName tableFn( table->Path() );
539 tableFn.SetPermissions( wxS_IRUSR | wxS_IRGRP | wxS_IROTH );
540
541 // CI containers commonly run as root, where the permission bits do not deny access
542 if( tableFn.IsFileWritable() )
543 {
544 BOOST_TEST_MESSAGE( "Skipping read-only table check; file remains writable (running as "
545 "root?)" );
546 tableFn.SetPermissions( wxS_IRUSR | wxS_IWUSR );
547 return;
548 }
549
550 IMPORTED_SAMPLE sample = importSample( project );
551
552 const wxString cacheNick = wxS( "rotable-import-syms" );
553 SYMBOL_IMPORT_RECONCILER reconciler( *adapter, project.GetProjectPath() );
554
556 sample.m_schematic.get(), std::move( sample.m_definitions ), cacheNick, {} );
557
558 BOOST_CHECK( result.m_cacheNickname.IsEmpty() );
559 BOOST_CHECK_EQUAL( result.m_linkedToCache, 0 );
560 BOOST_CHECK_GT( result.m_unresolved, 0 );
561
562 tableFn.SetPermissions( wxS_IRUSR | wxS_IWUSR );
563}
564
565
566// An unregistered library already sitting at the cache path must never be overwritten
567BOOST_AUTO_TEST_CASE( ExistingUserLibraryIsNotClobbered )
568{
569 PROJECT& project = m_staged.Project();
570
571 IMPORTED_SAMPLE sample = importSample( project );
572
574 BOOST_REQUIRE( adapter );
575
576 const wxString cacheNick = wxS( "victim-import-syms" );
577
578 wxFileName victim( project.GetProjectPath(), cacheNick,
580
581 const wxString sentinel = wxS( "(kicad_symbol_lib (version 20231120) (generator \"qa\"))" );
582 BOOST_REQUIRE( wxFile( victim.GetFullPath(), wxFile::write ).Write( sentinel ) );
583
584 SYMBOL_IMPORT_RECONCILER reconciler( *adapter, project.GetProjectPath() );
585
587 sample.m_schematic.get(), std::move( sample.m_definitions ), cacheNick, {} );
588
589 // the symbols stay unresolved rather than the file being taken over
590 BOOST_CHECK( result.m_cacheNickname.IsEmpty() );
591 BOOST_CHECK_GT( result.m_unresolved, 0 );
592
593 wxString contents;
594 wxFile readBack( victim.GetFullPath(), wxFile::read );
595 BOOST_REQUIRE( readBack.ReadAll( &contents ) );
596 BOOST_CHECK_EQUAL( contents, sentinel );
597}
598
599
const char * name
EE_TYPE OfType(KICAD_T aType) const
Definition sch_rtree.h:248
std::optional< LIBRARY_TABLE * > ProjectTable() const
Retrieves the project library table for this adapter type, or nullopt if one doesn't exist.
void LoadProjectTables(std::initializer_list< LIBRARY_TABLE_TYPE > aTablesToLoad={})
(Re)loads the project library tables in the given list, or all tables if no list is given
void SetNickname(const wxString &aNickname)
void SetType(const wxString &aType)
void SetURI(const wxString &aUri)
void SetScope(LIBRARY_TABLE_SCOPE aScope)
const wxString & URI() const
bool HasRow(const wxString &aNickname) const
A logical library item identifier and consists of various portions much like a URI.
Definition lib_id.h:45
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
Define a library symbol object.
Definition lib_symbol.h:119
std::vector< SCH_PIN * > GetPins() const override
virtual LIBRARY_MANAGER & GetLibraryManager() const
Definition pgm_base.h:125
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:183
Holds all the data relating to one schematic.
Definition schematic.h:148
SCH_SHEET_LIST Hierarchy() const
Return the full schematic flattened hierarchical sheet list.
void SetProject(PROJECT *aPrj)
void RefreshHierarchy()
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:165
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Definition sch_screen.h:118
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition sch_sheet.h:48
Schematic symbol object.
Definition sch_symbol.h:75
void SetLibId(const LIB_ID &aName)
const LIB_ID & GetLibId() const override
Definition sch_symbol.h:164
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition sch_symbol.h:183
Frame-independent, non-interactive service that reconciles the symbol-library references of a freshly...
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.
An interface to the global shared library manager that is schematic-specific and linked to one projec...
std::optional< LIB_STATUS > LoadOne(LIB_DATA *aLib) override
Loads or reloads the given library, if it exists.
LIB_SYMBOL * LoadSymbol(const wxString &aNickname, const wxString &aName)
Load a LIB_SYMBOL having aName from the library given by aNickname.
A wrapper for reporting to a wxString object.
Definition reporter.h:242
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
std::string GetTestDataRootDir()
PGM_BASE & Pgm()
The global program "get" accessor.
see class PGM_BASE
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
Outcome of a post-import symbol-library reconciliation pass.
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
IbisParser parser & reporter
BOOST_TEST_MESSAGE("Polyline has "<< chain.PointCount()<< " points")
BOOST_AUTO_TEST_CASE(EasyEdaProV3SchematicResolvesToGeneratedCache)
wxString result
Test unit parsing edge cases and error handling.
BOOST_CHECK_EQUAL(result, "25.4")
@ SCH_SYMBOL_T
Definition typeinfo.h:168
Definition of file extensions used in Kicad.