-
Notifications
You must be signed in to change notification settings - Fork 3
Add IfConfigDeclSyntax support for conditional compilation
#137
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #137 +/- ##
==========================================
+ Coverage 69.76% 73.35% +3.59%
==========================================
Files 73 73
Lines 3678 3866 +188
==========================================
+ Hits 2566 2836 +270
+ Misses 1112 1030 -82 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
IfConfigDeclSyntax support for conditional compilation in protocolsIfConfigDeclSyntax support for conditional compilation
Tests/MockingMacrosTests/Macros/MockedMacro/Mocked_IfConfigDeclTests.swift
Outdated
Show resolved
Hide resolved
graycampbell
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some comments/suggestions from my first pass through this
a0fc588 to
dce8d14
Compare
| var seenNames: Set<String> = [] | ||
| let uniqueAssociatedTypes = associatedTypeDeclarations.filter { decl in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| var seenNames: Set<String> = [] | |
| let uniqueAssociatedTypes = associatedTypeDeclarations.filter { decl in | |
| var seenNames = Set<String>() | |
| let uniqueAssociatedTypes = associatedTypeDeclarations.filter { | |
| seenNames.insert($0.name.text).inserted | |
| } |
Q: Does order matter? If not then Set(associatedTypeDeclarations) will work
graycampbell
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a hole in how all of this is implemented at the moment. See my comment below about the mock's generic parameter constraints.
| for associatedTypeDeclaration in uniqueAssociatedTypes { | ||
| let genericParameterName = associatedTypeDeclaration.name.trimmed | ||
|
|
||
| if let inheritanceClause = associatedTypeDeclaration.inheritanceClause { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's actually an issue with this PR as it stands right now. Right here (the code contained in this if block), is why the above deduplication of the associated types by name doesn't work.
Problem
If you have a protocol like this:
protocol SomeCollection {
#if DEBUG
associatedtype Item: Equatable
#else
associatedtype Item: Hashable
#endif
}This current implementation is going to create this mock:
final class SomeCollectionMock<Item: Equatable>: SomeCollection {}But that means the mock will only compile properly for DEBUG.
Possible Solution
If there are any associated types inside #if statements, we need to change how we handle the mock’s generic parameter constraints. So for the example above:
protocol SomeCollection {
#if DEBUG
associatedtype Item: Equatable
#else
associatedtype Item: Hashable
#endif
}We shouldn't emit:
final class SomeCollectionMock<Item: Equatable>: SomeCollection {}We should emit:
final class SomeCollectionMock<Item> {}
#if DEBUG
extension SomeCollectionMock: SomeCollection where Item: Equatable {}
#else
extension SomeCollectionMock: SomeCollection where Item: Hashable {}
#endifProtocols with #if/#elseif/#else/#endif blocks now have their members correctly mocked with the conditional compilation structure preserved. This includes support for methods, properties, initializers, and associated types within conditional blocks. Closes #136 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…sted conditionals - Move ifConfig processing inline in mockMemberBlock to match structure of other declaration types - Add unit tests for OR conditions (#if DEBUG || TESTFLIGHT) - Add unit tests for nested #if conditionals Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Extract mockMemberBlockItems helper that works on MemberBlockItemListSyntax - mockMemberBlock delegates to shared helper - mockIfConfigDeclaration uses shared helper directly - Remove mockIfConfigClause entirely (-46 lines) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When a protocol defines the same associated type with different constraints across #if branches (e.g., Item: Equatable in DEBUG vs Item: Hashable otherwise), generate a mock class without constraints plus conditional extensions that conform with the appropriate constraints for each branch. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…ed associatedType
0a1efbf to
835b842
Compare
📝 Summary
Protocols with
#if/#elseif/#else/#endifblocks now have their members correctly mocked with the conditional compilation structure preserved. This includes support for methods, properties, initializers, and associated types within conditional blocks.🛠️ Type of Change
🧪 How Has This Been Tested?
Ran all unit tests.
🔗 Related PRs or Issues
Closes #136
✅ Checklist
SwiftFormat