Skip to content

Read custom target paths from Package.swift for project index modules - #2910

Merged
calda merged 1 commit into
nicklockwood:developfrom
SwastikTripathi:fix/package-target-custom-paths
Nov 14, 2026
Merged

calda merged 1 commit into
nicklockwood:developfrom
SwastikTripathi:fix/package-target-custom-paths

Conversation

@SwastikTripathi

Copy link
Copy Markdown
Contributor

In a Swift package whose target uses a custom path:, files get no module in the project index, so the index-aware rules fall back to their single-file heuristics. With propertyTypes that produces code that doesn't compile. SwiftFormat's own repo is an example (.target(name: "SwiftFormat", path: "Sources")):

// Sources/ProjectIndexSnapshot.swift
var sourceIndexVersion = SourceFileIndex.cacheVersion

// swiftformat Sources --rules propertyTypes --property-types explicit
var sourceIndexVersion: SourceFileIndex = SourceFileIndex.cacheVersion
// error: member 'cacheVersion' in 'SourceFileIndex' produces result of type 'Int', but context expects 'SourceFileIndex'

cacheVersion is static let cacheVersion = 12 in ProjectIndex.swift. With a conventional layout (Sources/<Target>/...), or with no Package.swift at all, the index knows that and the line is left alone. A minimal package shows the same thing:

// Package.swift: .target(name: "M", path: "Sources")
// Sources/A.swift
struct S { static let v = 12 }
// Sources/B.swift
struct C { var x = S.v }   // becomes `var x: S = S.v`

moduleIdentifiers(for:in:) only assigned a module to files at Sources/<Target>/ or Tests/<Target>/. Anything else got none, and propertyTypeContext() then builds an index of the current file only.

The change:

  • swiftPackageTargetPaths(in:) reads the path: argument of target declarations (.target, .executableTarget, .testTarget, .macro, .plugin, .systemLibrary) in Package.swift. .package(path:) dependencies, absolute paths and paths with .. are ignored. A target whose arguments can't be read this simply (for example a .product(...) dependency before path:) keeps the old convention, so the result is never less conservative than before.
  • Files under one of those paths share one module per path (the longest matching path wins). Other files are handled exactly as before.
  • Package.swift is now part of the project index configuration hashes, so changing a target path invalidates the cached snapshot like an Xcode project change does.

Tests: a package with path: "Sources" (a file directly in Sources/ and one in Sources/Rules/ get the same module), path: "./Tool/", a conventional test target and an unrelated directory; .package(path:) entries being ignored; and the manifest hash. They fail on develop (4 failures). The full suite passes (7635 tests).

Found by formatting SwiftFormat's own Sources with all rules enabled (except the ones that are opt-in for known reasons, like preferSwiftStringAPI) and building it: the three cacheVersion errors were the only build failures, and the build is clean with this change.

@codecov

codecov Bot commented Nov 12, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.13%. Comparing base (a615702) to head (bc22039).

Additional details and impacted files
@@           Coverage Diff            @@
##           develop    #2910   +/-   ##
========================================
  Coverage    96.13%   96.13%           
========================================
  Files          206      206           
  Lines        35512    35538   +26     
========================================
+ Hits         34140    34166   +26     
  Misses        1372     1372           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@calda
calda merged commit c2294eb into nicklockwood:develop Nov 14, 2026
16 of 17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants