diff --git a/src/Mod/Assembly/App/AssemblyLink.cpp b/src/Mod/Assembly/App/AssemblyLink.cpp index 48e8c8d1cc..4263c3ecee 100644 --- a/src/Mod/Assembly/App/AssemblyLink.cpp +++ b/src/Mod/Assembly/App/AssemblyLink.cpp @@ -311,6 +311,19 @@ void AssemblyLink::updateContents() purgeTouched(); } +// Generate an instance label for assembly components by appending a -N suffix. +// All instances get a suffix (starting at -1) so that structured part numbers +// like "P03-0001" are never mangled by UniqueNameManager's trailing-digit logic. +static std::string makeInstanceLabel(App::Document* doc, const std::string& baseLabel) +{ + for (int i = 1;; ++i) { + std::string candidate = baseLabel + "-" + std::to_string(i); + if (!doc->containsLabel(candidate)) { + return candidate; + } + } +} + void AssemblyLink::synchronizeComponents() { App::Document* doc = getDocument(); @@ -428,7 +441,7 @@ void AssemblyLink::synchronizeComponents() auto* subAsmLink = static_cast(newObj); subAsmLink->LinkedObject.setValue(obj); subAsmLink->Rigid.setValue(asmLink->Rigid.getValue()); - subAsmLink->Label.setValue(obj->Label.getValue()); + subAsmLink->Label.setValue(makeInstanceLabel(doc, obj->Label.getValue())); addObject(subAsmLink); link = subAsmLink; } @@ -440,7 +453,7 @@ void AssemblyLink::synchronizeComponents() ); newLink->LinkedObject.setValue(srcLink->getTrueLinkedObject(false)); - newLink->Label.setValue(obj->Label.getValue()); + newLink->Label.setValue(makeInstanceLabel(doc, obj->Label.getValue())); addObject(newLink); newLink->ElementCount.setValue(srcLink->ElementCount.getValue()); @@ -461,7 +474,7 @@ void AssemblyLink::synchronizeComponents() App::DocumentObject* newObj = doc->addObject("App::Link", obj->getNameInDocument()); auto* newLink = static_cast(newObj); newLink->LinkedObject.setValue(obj); - newLink->Label.setValue(obj->Label.getValue()); + newLink->Label.setValue(makeInstanceLabel(doc, obj->Label.getValue())); addObject(newLink); link = newLink; } diff --git a/tests/src/Base/UniqueNameManager.cpp b/tests/src/Base/UniqueNameManager.cpp index ba502eafd2..20955efec8 100644 --- a/tests/src/Base/UniqueNameManager.cpp +++ b/tests/src/Base/UniqueNameManager.cpp @@ -122,4 +122,15 @@ TEST(UniqueNameManager, UniqueNameWith9NDigits) manager.addExactName("Compound123456789"); EXPECT_EQ(manager.makeUniqueName("Compound", 3), "Compound123456790"); } +TEST(UniqueNameManager, StructuredPartNumberDecomposition) +{ + // Structured part numbers like P03-0001 have their trailing digits + // treated as the uniquifying suffix by UniqueNameManager. This is + // correct for default FreeCAD objects (Body -> Body001) but wrong + // for structured identifiers. Assembly module handles this separately + // via makeInstanceLabel which appends -N instance suffixes instead. + Base::UniqueNameManager manager; + manager.addExactName("P03-0001"); + EXPECT_EQ(manager.makeUniqueName("P03-0001", 3), "P03-0002"); +} // NOLINTEND(cppcoreguidelines-*,readability-*)