feat: add traits to XCRemoteSwiftPackageReference and XCLocalSwiftPackageReference#1114
feat: add traits to XCRemoteSwiftPackageReference and XCLocalSwiftPackageReference#1114chigichan24 wants to merge 4 commits intotuist:mainfrom
traits to XCRemoteSwiftPackageReference and XCLocalSwiftPackageReference#1114Conversation
| /* Begin XCLocalSwiftPackageReference section */ | ||
| C9FDF5C52AD604310096A37A /* XCLocalSwiftPackageReference "MyLocalPackage" */ = { | ||
| isa = XCLocalSwiftPackageReference; | ||
| relativePath = MyLocalPackage; | ||
| traits = ( | ||
| NoUIFramework, | ||
| ); | ||
| }; | ||
| /* End XCLocalSwiftPackageReference section */ | ||
|
|
||
| /* Begin XCRemoteSwiftPackageReference section */ | ||
| 42AA19FF22AAF0D600428760 /* XCRemoteSwiftPackageReference "RxSwift" */ = { | ||
| isa = XCRemoteSwiftPackageReference; | ||
| repositoryURL = "https://github.com/ReactiveX/RxSwift"; | ||
| requirement = { | ||
| kind = upToNextMajorVersion; | ||
| minimumVersion = 5.0.1; | ||
| }; | ||
| traits = ( | ||
| ); | ||
| }; | ||
| /* End XCRemoteSwiftPackageReference section */ |
There was a problem hiding this comment.
note: The reason of PR diff size is XL.
Fixtures/iOS/ProjectWithSwiftPackageTraits.xcodeproj/project.pbxproj is ~600 lines, which makes this PR look larger than it is. It's a copy of the existing ProjectWithXCLocalSwiftPackageReference.xcodeproj fixture with traits = ( ... ); entries added to the Remote and Local reference sections
The substantive delta from the source fixture is few lines (diff output):
< buildConfigurationList = ... "ProjectWithXCLocalSwiftPackageReference" ...;
> buildConfigurationList = ... "ProjectWithSwiftPackageTraits" ...;
< ... "ProjectWithXCLocalSwiftPackageReference" = { ...
> ... "ProjectWithSwiftPackageTraits" = { ...
+ traits = (
+ NoUIFramework,
+ );
+ traits = (
+ );A new fixture is used rather than modifying the existing one so that testReadWriteProducesNoDiff on ProjectWithXCLocalSwiftPackageReference.xcodeproj stays stable — adding traits = ( ... ); to that existing fixture would have changed what its existing assertion produces and entangled this change with unrelated local-package add/delete tests.
Resolves #1113
Short description 📝
Add support for Swift Package traits (SE-0450) on
XCRemoteSwiftPackageReferenceandXCLocalSwiftPackageReference, matching thetraits = ( ... );format that Xcode 26.4+ writes intoproject.pbxproj. Without this, any call toXcodeProj.write()on a trait-configured project silently discards the user's trait selection, and Xcode falls back to default traits on next open.Solution 📦
Add optional
traits: [String]?on both reference types:decodeIfPresentfor reading,if let ... { ... }guard inplistKeyAndValuefor writing — same shape already used by other optional fields on these types (e.g.versionRequirement).niland[]distinct. SE-0450 treatstraits: []as explicitly disable default traits, semantically different from no selection. Both forms appear in real-world pbxproj output today:sentry-cocoamacOS CLI sample:traits = ( NoUIFramework, );mlx-swift-examples:traits = ( );XCSwiftPackageProductDependencyis intentionally not modified — sampling several real pbxproj files shows Xcode does not emittraitson product-dependency entries; the selection lives on the reference side only.Alternatives considered:
Set<String>?instead of[String]?— rejected because pbxproj arrays preserve source-file order and XcodeProj prioritizes fidelity to the on-disk representation over UI semantics.Bool— rejected because it loses the SE-0450 distinction between "use defaults" and "no traits".While wiring the equality check in, a pre-existing gap surfaced: no
isEqual(to:)overload was synthesized forXCLocalSwiftPackageReferenceinEquality.generated.swift, so theoverride func isEqual(to object: Any?)fell back to thePBXContainerItemsuper and silently ignoredrelativePath. The first commit adds the missing entry (equivalent to what Sourcery would generate) as an independent prep step so the traits-specific changes stay minimal.A standalone reproducer comparing stock 9.11.0 vs this branch side-by-side lives at https://github.com/chigichan24/XcodeProj-MinimalProject.
Implementation 👩💻👨💻
XCLocalSwiftPackageReferenceentry toEquality.generated.swift(prep — unrelated to traits but needed so the newtraitscomparison actually takes effect)traits: [String]?toXCRemoteSwiftPackageReference(init parameter,CodingKeys,decodeIfPresent, conditionalplistKeyAndValueencode, equality entry) plus unit tests for decode / encode / equalityXCLocalSwiftPackageReferencewith matching unit testsFixtures/iOS/ProjectWithSwiftPackageTraits.xcodeprojcovering both populated and empty-arraytraits, and extendXcodeProjIntegrationTestswith atestReadWriteProducesNoDiffcase over the new fixture