Repository navigation
Commit b8cc821
Give a library whose Swift name collides its npm scope back
A dependency's Swift name is derived from its npm package name with the scope
dropped, which makes two collisions unavoidable: `@powersync/react-native`
derives `ReactNative`, one of React Native's own names, and `@a/foo` and
`@b/foo` both derive `Foo`. Either was emitted into the package graph as-is, and
SwiftPM then failed deep inside dependency resolution with a duplicate-name
error that named neither the library nor the react-native.config.js that caused
it.
The scope that was dropped is the fix. A scoped dep whose derived name is
reserved gets the TitleCased scope prepended (`PowersyncReactNative`), and deps
that resolved to the same name get it prepended too (`AFoo`, `BFoo`), so the
library author has nothing to do. Every disambiguation logs one line naming the
package, the name it would have taken and the name it got. Nothing can regress
on this — both collisions fail SwiftPM resolution today, so no working library
carries such a name and no consumer imports headers under it.
The two cases need different shapes. A reserved name is decidable per dep, so it
resolves in `resolveSwiftName`. A collision with another dep is not visible from
there, so it is a pass over the resolved set: group by name, and prepend the
scope to every scoped member of a group larger than one. Every member moves
rather than one arbitrary winner staying put, since there is no non-arbitrary
winner. Two members never move: a name the author set with `spm.name` (their
choice wins, and the others move around it) and an unscoped one (no scope to
borrow).
The pass runs once, and then the whole set is validated — this is the part that
has to be right. A borrowed scope can land on a name another dep already holds
(`@a/foo` → `AFoo`, next to a package `a-foo`) or on a reserved one, and two
libraries silently sharing a name is worse than the error this replaces. So both
existing checks now run over the final set, and anything a scope could not
resolve still fails with the message it did before: two unscoped deps deriving
the same name, an explicit `spm.name` that is reserved, a group whose only
scoped member's new name is taken. Retrying instead of failing would trade a
diagnosable error for a name nobody can predict.
Reserving the names React Native puts in a manifest is what makes the first case
diagnosable at all. Matching is case-insensitive throughout: a name that differs
from another only in case is not distinct enough for the build to keep the two
apart. The reserved check runs before the dep-vs-dep one, so the more specific
diagnosis wins, and it runs for a library that ships an autolinking plugin too:
`spm scaffold` knows nothing about plugins, so an exemption there would leave
the two commands disagreeing about the same library.
`SpmNameCollisionError` distinguishes a misconfiguration from a resolution
failure, so `scaffoldAll` — which degrades to the direct deps when a transitive
dep can't be found — still surfaces it instead of scaffolding manifests SPM
will reject. Its remote package config moves out of the same try for the same
reason.
Every Swift name reaching a manifest now comes from that one resolved set: the
autolinker's two `toSwiftName` fallbacks would have re-derived the
pre-disambiguation name and emitted a reference nothing matches, so they are
replaced by a required lookup that fails loudly.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>1 parent 0c7f63a commit b8cc821
8 files changed
Lines changed: 1155 additions & 72 deletions
File tree
- packages/react-native/scripts/spm
- __tests__
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
| 13 | + | |
13 | 14 | | |
14 | 15 | | |
15 | 16 | | |
| 17 | + | |
16 | 18 | | |
17 | 19 | | |
18 | 20 | | |
| |||
1082 | 1084 | | |
1083 | 1085 | | |
1084 | 1086 | | |
1085 | | - | |
| 1087 | + | |
1086 | 1088 | | |
1087 | 1089 | | |
1088 | 1090 | | |
| |||
1095 | 1097 | | |
1096 | 1098 | | |
1097 | 1099 | | |
1098 | | - | |
| 1100 | + | |
1099 | 1101 | | |
1100 | 1102 | | |
1101 | 1103 | | |
| |||
1121 | 1123 | | |
1122 | 1124 | | |
1123 | 1125 | | |
1124 | | - | |
| 1126 | + | |
| 1127 | + | |
| 1128 | + | |
1125 | 1129 | | |
1126 | 1130 | | |
1127 | 1131 | | |
| |||
1154 | 1158 | | |
1155 | 1159 | | |
1156 | 1160 | | |
| 1161 | + | |
| 1162 | + | |
| 1163 | + | |
| 1164 | + | |
| 1165 | + | |
| 1166 | + | |
| 1167 | + | |
| 1168 | + | |
| 1169 | + | |
| 1170 | + | |
| 1171 | + | |
| 1172 | + | |
| 1173 | + | |
| 1174 | + | |
| 1175 | + | |
| 1176 | + | |
| 1177 | + | |
| 1178 | + | |
| 1179 | + | |
1157 | 1180 | | |
1158 | 1181 | | |
1159 | 1182 | | |
| |||
1532 | 1555 | | |
1533 | 1556 | | |
1534 | 1557 | | |
| 1558 | + | |
| 1559 | + | |
| 1560 | + | |
| 1561 | + | |
| 1562 | + | |
| 1563 | + | |
| 1564 | + | |
| 1565 | + | |
| 1566 | + | |
| 1567 | + | |
| 1568 | + | |
| 1569 | + | |
| 1570 | + | |
| 1571 | + | |
| 1572 | + | |
| 1573 | + | |
| 1574 | + | |
| 1575 | + | |
| 1576 | + | |
| 1577 | + | |
| 1578 | + | |
| 1579 | + | |
| 1580 | + | |
| 1581 | + | |
| 1582 | + | |
| 1583 | + | |
| 1584 | + | |
| 1585 | + | |
| 1586 | + | |
| 1587 | + | |
| 1588 | + | |
| 1589 | + | |
| 1590 | + | |
| 1591 | + | |
| 1592 | + | |
| 1593 | + | |
| 1594 | + | |
| 1595 | + | |
| 1596 | + | |
| 1597 | + | |
| 1598 | + | |
| 1599 | + | |
| 1600 | + | |
| 1601 | + | |
| 1602 | + | |
| 1603 | + | |
| 1604 | + | |
| 1605 | + | |
| 1606 | + | |
| 1607 | + | |
| 1608 | + | |
| 1609 | + | |
| 1610 | + | |
| 1611 | + | |
| 1612 | + | |
| 1613 | + | |
| 1614 | + | |
| 1615 | + | |
| 1616 | + | |
| 1617 | + | |
| 1618 | + | |
| 1619 | + | |
| 1620 | + | |
| 1621 | + | |
| 1622 | + | |
| 1623 | + | |
| 1624 | + | |
| 1625 | + | |
| 1626 | + | |
| 1627 | + | |
| 1628 | + | |
| 1629 | + | |
| 1630 | + | |
| 1631 | + | |
| 1632 | + | |
| 1633 | + | |
| 1634 | + | |
| 1635 | + | |
| 1636 | + | |
| 1637 | + | |
| 1638 | + | |
| 1639 | + | |
| 1640 | + | |
| 1641 | + | |
| 1642 | + | |
| 1643 | + | |
| 1644 | + | |
| 1645 | + | |
| 1646 | + | |
| 1647 | + | |
| 1648 | + | |
| 1649 | + | |
| 1650 | + | |
| 1651 | + | |
| 1652 | + | |
| 1653 | + | |
| 1654 | + | |
| 1655 | + | |
| 1656 | + | |
| 1657 | + | |
| 1658 | + | |
| 1659 | + | |
| 1660 | + | |
| 1661 | + | |
| 1662 | + | |
| 1663 | + | |
| 1664 | + | |
| 1665 | + | |
| 1666 | + | |
| 1667 | + | |
| 1668 | + | |
| 1669 | + | |
| 1670 | + | |
| 1671 | + | |
| 1672 | + | |
| 1673 | + | |
| 1674 | + | |
| 1675 | + | |
| 1676 | + | |
| 1677 | + | |
| 1678 | + | |
| 1679 | + | |
| 1680 | + | |
| 1681 | + | |
| 1682 | + | |
| 1683 | + | |
| 1684 | + | |
| 1685 | + | |
| 1686 | + | |
| 1687 | + | |
| 1688 | + | |
| 1689 | + | |
| 1690 | + | |
| 1691 | + | |
| 1692 | + | |
| 1693 | + | |
| 1694 | + | |
| 1695 | + | |
| 1696 | + | |
| 1697 | + | |
| 1698 | + | |
| 1699 | + | |
| 1700 | + | |
| 1701 | + | |
| 1702 | + | |
| 1703 | + | |
| 1704 | + | |
| 1705 | + | |
| 1706 | + | |
| 1707 | + | |
| 1708 | + | |
| 1709 | + | |
| 1710 | + | |
| 1711 | + | |
| 1712 | + | |
| 1713 | + | |
| 1714 | + | |
| 1715 | + | |
| 1716 | + | |
| 1717 | + | |
| 1718 | + | |
| 1719 | + | |
| 1720 | + | |
| 1721 | + | |
| 1722 | + | |
| 1723 | + | |
| 1724 | + | |
| 1725 | + | |
| 1726 | + | |
| 1727 | + | |
| 1728 | + | |
| 1729 | + | |
| 1730 | + | |
| 1731 | + | |
| 1732 | + | |
| 1733 | + | |
| 1734 | + | |
| 1735 | + | |
| 1736 | + | |
| 1737 | + | |
| 1738 | + | |
| 1739 | + | |
| 1740 | + | |
| 1741 | + | |
| 1742 | + | |
| 1743 | + | |
| 1744 | + | |
| 1745 | + | |
| 1746 | + | |
| 1747 | + | |
| 1748 | + | |
| 1749 | + | |
| 1750 | + | |
| 1751 | + | |
| 1752 | + | |
| 1753 | + | |
| 1754 | + | |
| 1755 | + | |
| 1756 | + | |
| 1757 | + | |
| 1758 | + | |
| 1759 | + | |
| 1760 | + | |
| 1761 | + | |
| 1762 | + | |
| 1763 | + | |
| 1764 | + | |
| 1765 | + | |
| 1766 | + | |
| 1767 | + | |
| 1768 | + | |
| 1769 | + | |
| 1770 | + | |
| 1771 | + | |
| 1772 | + | |
| 1773 | + | |
0 commit comments