Move duplicate field handling into field parser

Fixes https://gitlab.com/kicad/code/kicad/-/issues/10130

(cherry picked from commit ea99c42df6)
This commit is contained in:
Jon Evans 2022-01-02 13:19:31 -05:00
parent ec83537576
commit 9daa4d0e2c
2 changed files with 20 additions and 25 deletions

View File

@ -162,14 +162,13 @@ LIB_SYMBOL* SCH_SEXPR_PARSER::ParseSymbol( LIB_SYMBOL_MAP& aSymbolLibMap, int aF
wxString name; wxString name;
wxString error; wxString error;
LIB_ITEM* item; LIB_ITEM* item;
LIB_FIELD* field;
std::unique_ptr<LIB_SYMBOL> symbol = std::make_unique<LIB_SYMBOL>( wxEmptyString ); std::unique_ptr<LIB_SYMBOL> symbol = std::make_unique<LIB_SYMBOL>( wxEmptyString );
std::set<int> fieldIDsRead;
m_requiredVersion = aFileVersion; m_requiredVersion = aFileVersion;
symbol->SetUnitCount( 1 ); symbol->SetUnitCount( 1 );
m_fieldId = MANDATORY_FIELDS; m_fieldId = MANDATORY_FIELDS;
m_fieldIDsRead.clear();
token = NextTok(); token = NextTok();
@ -232,29 +231,7 @@ LIB_SYMBOL* SCH_SEXPR_PARSER::ParseSymbol( LIB_SYMBOL_MAP& aSymbolLibMap, int aF
break; break;
case T_property: case T_property:
field = parseProperty( symbol ); parseProperty( symbol );
if( field )
{
// Due to an bug when in #LIB_SYMBOL::Flatten, duplicate ids slipped through
// when writing files. This section replaces duplicate #LIB_FIELD indices on
// load.
if( fieldIDsRead.count( field->GetId() ) )
{
int nextAvailableId = field->GetId() + 1;
while( fieldIDsRead.count( nextAvailableId ) )
nextAvailableId += 1;
fieldIDsRead.insert( nextAvailableId );
field->SetId( nextAvailableId );
}
else if( field )
{
fieldIDsRead.insert( field->GetId() );
}
}
break; break;
case T_extends: case T_extends:
@ -781,6 +758,19 @@ LIB_FIELD* SCH_SEXPR_PARSER::parseProperty( std::unique_ptr<LIB_SYMBOL>& aSymbol
} }
} }
// Due to an bug when in #LIB_SYMBOL::Flatten, duplicate ids slipped through
// when writing files. This section replaces duplicate #LIB_FIELD indices on
// load.
if( m_fieldIDsRead.count( field->GetId() ) )
{
int nextAvailableId = field->GetId() + 1;
while( m_fieldIDsRead.count( nextAvailableId ) )
nextAvailableId += 1;
field->SetId( nextAvailableId );
}
LIB_FIELD* existingField; LIB_FIELD* existingField;
if( field->GetId() < MANDATORY_FIELDS ) if( field->GetId() < MANDATORY_FIELDS )
@ -788,6 +778,7 @@ LIB_FIELD* SCH_SEXPR_PARSER::parseProperty( std::unique_ptr<LIB_SYMBOL>& aSymbol
existingField = aSymbol->GetFieldById( field->GetId() ); existingField = aSymbol->GetFieldById( field->GetId() );
*existingField = *field; *existingField = *field;
m_fieldIDsRead.insert( field->GetId() );
return existingField; return existingField;
} }
else if( name == "ki_keywords" ) else if( name == "ki_keywords" )
@ -853,6 +844,7 @@ LIB_FIELD* SCH_SEXPR_PARSER::parseProperty( std::unique_ptr<LIB_SYMBOL>& aSymbol
if( !existingField ) if( !existingField )
{ {
aSymbol->AddDrawItem( field.get(), false ); aSymbol->AddDrawItem( field.get(), false );
m_fieldIDsRead.insert( field->GetId() );
return field.release(); return field.release();
} }
else else

View File

@ -82,6 +82,9 @@ class SCH_SEXPR_PARSER : public SCHEMATIC_LEXER
int m_convert; ///< The current body style being parsed. int m_convert; ///< The current body style being parsed.
wxString m_symbolName; ///< The current symbol name. wxString m_symbolName; ///< The current symbol name.
/// Field IDs that have been read so far for the current symbol.
std::set<int> m_fieldIDsRead;
std::set<KIID> m_uuids; std::set<KIID> m_uuids;
PROGRESS_REPORTER* m_progressReporter; // optional; may be nullptr PROGRESS_REPORTER* m_progressReporter; // optional; may be nullptr