Skip to content

Add Spacing implementation #245

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

Merged
merged 2 commits into from
Apr 6, 2025
Merged

Add Spacing implementation #245

merged 2 commits into from
Apr 6, 2025

Conversation

Kyle-Ye
Copy link
Member

@Kyle-Ye Kyle-Ye commented Apr 6, 2025

Summary by CodeRabbit

  • New Features

    • Enhanced layout spacing with a more flexible and public Spacing struct, now supporting complex spacing definitions and calculations.
    • Introduced new categories and metrics for improved management of spacing in layouts, including support for layout direction considerations.
    • Simplified the spacing() method in the layout system to return an empty Spacing object.
  • Tests

    • Added comprehensive test coverage for the new Spacing functionality, validating various aspects such as category uniqueness, spacing calculations, and method behaviors.

Copy link

coderabbitai bot commented Apr 6, 2025

Walkthrough

The changes update the Spacing module within OpenSwiftUICore. The Spacing.swift file now defines a public Spacing struct conforming to Equatable and Sendable, with new nested structs (Category, Key, TextMetrics) and an enum (Value). A default spacing constant, a minima dictionary, and several new methods for computing spacing between views and managing spacing state (incorporate, clear, reset) were introduced. A new test suite in SpacingTests.swift has been added to validate the expanded functionality and API behavior.

Changes

File(s) Change Summary
Sources/.../Spacing.swift - Updated Spacing to public struct Spacing: Equatable, Sendable with revised header metadata
- Added defaultSpacingValue constant and minima dictionary
- Introduced nested structs: Category, Key, TextMetrics
- Added enum Value
- Added methods: distanceToSuccessorView(along:layoutDirection:preferring:), incorporate(_:), clear(_:), reset(_:)
- Added property isLayoutDirectionSymmetric and static methods for common spacing initializations
Tests/.../SpacingTests.swift - Added a comprehensive test suite covering initialization, equality, spacing calculations, layout direction symmetry, and state modifications of the Spacing module
Sources/.../LayoutComputer/LayoutComputer.swift - Modified spacing() method in DefaultDelegate to return an empty Spacing object instead of a specific minima dictionary for edge categories.

Sequence Diagram(s)

sequenceDiagram
    participant V as View
    participant S as Spacing
    participant L as LayoutChecker

    V->>S: distanceToSuccessorView(axis, layoutDirection, nextPreference)
    S->>S: Retrieve minima & default value
    S->>L: Check layout direction symmetry (isLayoutDirectionSymmetric)
    alt Symmetric Layout
        S-->>V: Return calculated spacing value
    else Asymmetric Layout
        S-->>V: Return adjusted spacing value (or nil)
    end
Loading

Poem

I'm a rabbit with a coder's delight,
Hopping through changes both day and night,
New structs and methods join in the fun,
With tests to ensure our work is well done,
Spacing and metrics now dance in the light!
🐇💻✨


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b8c7eb6 and a7ddcda.

📒 Files selected for processing (3)
  • Sources/OpenSwiftUICore/Layout/Geometry/Spacing.swift (1 hunks)
  • Sources/OpenSwiftUICore/Layout/LayoutComputer/LayoutComputer.swift (1 hunks)
  • Tests/OpenSwiftUICoreTests/Layout/Geometry/SpacingTests.swift (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • Tests/OpenSwiftUICoreTests/Layout/Geometry/SpacingTests.swift
🧰 Additional context used
🧬 Code Definitions (1)
Sources/OpenSwiftUICore/Layout/Geometry/Spacing.swift (1)
Tests/OpenSwiftUICoreTests/Layout/Geometry/SpacingTests.swift (9)
  • lineSpacing (105-109)
  • isAlmostEqual (85-93)
  • spacing (95-103)
  • distance (153-175)
  • incorporate (215-256)
  • clear (258-307)
  • reset (309-360)
  • distanceToSuccessorView (402-473)
  • description (545-610)
⏰ Context from checks skipped due to timeout of 90000ms (6)
  • GitHub Check: Execute tests on iOS (macos-15, 16.0, 2024, 18.0)
  • GitHub Check: Execute compatibility tests for macOS (macos-15, 16.0, 2024)
  • GitHub Check: Execute compatibility tests for iOS (macos-15, 16.0, 2024, 18.0)
  • GitHub Check: Execute tests on macOS (macos-15, 16.0, 2021)
  • GitHub Check: Execute tests on macOS (macos-15, 16.0, 2024)
  • GitHub Check: Execute tests on Ubuntu (6.0.1)
🔇 Additional comments (18)
Sources/OpenSwiftUICore/Layout/Geometry/Spacing.swift (17)

1-11: Header and import updates look good.

The file header has been properly updated with the latest audit information for iOS 18.0 and marked as complete. The package import for Foundation is appropriate for this module.


12-14: Good use of shared configuration for default spacing.

Defining a package-level constant defaultSpacingValue that references the shared value from CoreGlue centralizes this configuration and promotes consistency throughout the framework.


17-23: Well-structured public API expansion.

The Spacing struct is now correctly defined as public with Equatable and Sendable conformance, which is appropriate for a type that may be used across module boundaries and in concurrent contexts.


26-48: Category implementation uses effective type-based identification.

The Category struct uses type-based identification to uniquely identify different spacing categories. The implementation has proper hashing and equality methods using ObjectIdentifier for type comparison.


52-72: Key struct provides good spacing identification.

The Key struct effectively combines category and edge information to uniquely identify spacing values in the system. The implementation is clean and well-documented.


76-110: TextMetrics struct properly captures text dimensions.

The TextMetrics struct maintains vertical text dimensions (ascend, descend, leading) and pixel length for rounding, which are essential for calculating proper text spacing.


143-147: Review the text spacing calculation logic.

There's a comment on line 145 indicating uncertainty about the calculation in line 146. The formula appears complex and might benefit from additional explanation or verification.

// NOTE: Actually this is still bottom.leading 🤔
result = top.descend + bottom.lineSpacing - bottom.descend - top.descend - bottom.ascend

The calculation subtracts top.descend twice, which looks suspicious.

Please verify the calculation logic against the test cases in SpacingTests.swift to confirm it's correct.


159-232: Value enum handles spacing types effectively.

The Value enum provides a clean way to represent both fixed distances and text metrics-based spacing. The implementation of comparison operators and the distance calculation method is thorough and handles all possible combinations.


234-253: Incorporate method efficiently merges spacing values.

The incorporate method effectively merges values from another Spacing instance, taking the maximum when both have values for the same key. Good use of lazy filtering and the merge operation.


255-274: Clear methods properly handle edge removal.

The two clear methods (for Edge.Set with layout direction and for AbsoluteEdge.Set) effectively remove spacing values for specified edges. The implementation properly handles empty edge sets.


276-311: Reset methods handle edge resets with appropriate defaults.

The reset methods clear existing values and set appropriate defaults based on edge categories. The implementation correctly handles all edge cases and provides good documentation.


313-331: Good initializer implementations.

The implementation provides both a parameter-less initializer with reasonable defaults and a custom initializer that accepts a dictionary of spacing values. This gives flexibility when creating Spacing instances.


333-394: Complex but effective distance calculation.

The distanceToSuccessorView method and its private helper _distance implement a sophisticated algorithm for determining spacing between views. The code handles different scenarios like layout direction and edge types effectively.


398-437: Great CustomStringConvertible implementation.

The description property provides a detailed, well-formatted representation of the Spacing instance. The implementation sorts keys for consistent output, which is good for testing and debugging.


439-468: Useful symmetric layout property.

The isLayoutDirectionSymmetric property efficiently determines if spacing would produce the same visual results regardless of layout direction. This is valuable for internationalization support.


473-516: Helpful factory methods for common spacing patterns.

The static factory methods (zero, all, horizontal, vertical) provide convenient shortcuts for creating common spacing configurations, which improves API usability.


521-554: Comprehensive set of predefined categories.

The extension provides a complete set of static properties for common category types, making it easy to specify different kinds of text spacing without having to create categories manually.

Sources/OpenSwiftUICore/Layout/LayoutComputer/LayoutComputer.swift (1)

61-63: Simplified default spacing implementation.

The spacing() method now returns a simple Spacing() instance instead of what appears to have been a more complex initialization. This change aligns with the enhanced default initialization of the Spacing struct, which now provides appropriate default values automatically.

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@Kyle-Ye Kyle-Ye requested a review from Copilot April 6, 2025 16:56
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 1

🧹 Nitpick comments (2)
Tests/OpenSwiftUICoreTests/Layout/Geometry/SpacingTests.swift (1)

130-211: Consider adding negative spacing tests.

While the current tests are extensive, you could include a scenario with negative or zero distances to confirm correct behavior under edge cases.

Sources/OpenSwiftUICore/Layout/Geometry/Spacing.swift (1)

138-150: Clarify the note regarding bottom.leading.

The comment at line 145 indicates potential confusion about using bottom.leading. Consider revisiting or explaining the logic to avoid confusion.

🛑 Comments failed to post (1)
Sources/OpenSwiftUICore/Layout/Geometry/Spacing.swift (1)

249-251: 🛠️ Refactor suggestion

Address unused closure parameter.

Static analysis flagged the unused parameter value in the .filter { key, value in ... } closure. Replace value with _ to resolve the warning.

-.filter { key, value in
-    edges.contains(key.edge)
+.filter { key, _ in
+    edges.contains(key.edge)
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

                .filter { key, _ in
                    edges.contains(key.edge)
                }
🧰 Tools
🪛 SwiftLint (0.57.0)

[Warning] 249-249: Unused parameter in a closure should be replaced with _

(unused_closure_parameter)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
Sources/OpenSwiftUICore/Layout/Geometry/Spacing.swift (2)

10-10: Check nonstandard Swift package syntax.
“package import Foundation” is unusual in mainstream Swift. Confirm that your build setup supports the “package” keyword; otherwise, regular import Foundation should suffice.


234-253: Minor SwiftLint warning: Unused closure parameter “value”.
You only use key in the .filter closure at line 249. SwiftLint suggests using _ in place of the unused parameter.

- .filter { key, value in edges.contains(key.edge) }
+ .filter { key, _ in edges.contains(key.edge) }
🧰 Tools
🪛 SwiftLint (0.57.0)

[Warning] 249-249: Unused parameter in a closure should be replaced with _

(unused_closure_parameter)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f75250d and b8c7eb6.

📒 Files selected for processing (2)
  • Sources/OpenSwiftUICore/Layout/Geometry/Spacing.swift (1 hunks)
  • Tests/OpenSwiftUICoreTests/Layout/Geometry/SpacingTests.swift (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • Tests/OpenSwiftUICoreTests/Layout/Geometry/SpacingTests.swift
🧰 Additional context used
🧬 Code Definitions (1)
Sources/OpenSwiftUICore/Layout/Geometry/Spacing.swift (1)
Tests/OpenSwiftUICoreTests/Layout/Geometry/SpacingTests.swift (9)
  • lineSpacing (105-109)
  • isAlmostEqual (85-93)
  • spacing (95-103)
  • distance (153-175)
  • incorporate (215-256)
  • clear (258-307)
  • reset (309-360)
  • distanceToSuccessorView (402-473)
  • description (545-610)
🪛 SwiftLint (0.57.0)
Sources/OpenSwiftUICore/Layout/Geometry/Spacing.swift

[Warning] 249-249: Unused parameter in a closure should be replaced with _

(unused_closure_parameter)

🔇 Additional comments (13)
Sources/OpenSwiftUICore/Layout/Geometry/Spacing.swift (13)

3-3: Header updates look good.
The bump in iOS audit version to 18.0 and status completion markers appear consistent with your versioning approach. No issues here.

Also applies to: 5-8


12-13: Validate default spacing source.
Referencing CoreGlue.shared.defaultSpacing is fine if you are certain CoreGlue is initialized before use. Ensure that no race condition or lazy property needs special handling.


17-23: Well-documented struct introduction.
Your doc comments effectively describe Spacing usage and context. Great clarity here.


24-25: Organized MARK usage.
Using “// MARK: -” improves code readability.


26-72: Spacing.Category and Spacing.Key look sound.
These structs are succinct, aligning categories and edges with minimal overhead. Their hashable conformance also looks consistent.


74-154: TextMetrics implementation is logically consistent.
The properties (ascend, descend, leading, pixelLength) and related methods (including isAlmostEqual and spacing) appear correct. However, note the comment at line 145 (“Actually this is still bottom.leading 🤔”). Please verify that the arithmetic accurately matches your intended spacing rules.


157-232: Value enum captures spacing variants well.
Supporting both distances and text metrics is a flexible design. Pattern matching in distance(to:) is clearly structured.


255-311: clear and reset methods are thoughtfully designed.
They handle edges appropriately for both absolute and direction-based sets. The approach of removing preexisting values before optionally resetting them to zero is cohesive with the rest of your spacing system.


313-331: Constructors provide flexible initialization.
You offer a default constructor with standard minimal edges, plus an override for explicitly setting the dictionary. This is a helpful combination.


333-394: distanceToSuccessorView & _distance logic.
These methods correctly combine matching categories between two Spacing instances. The fallback to uncategorized edges is a good safeguard. Good job ensuring different layout directions are handled.


397-468: CustomStringConvertible and isLayoutDirectionSymmetric.
Providing a descriptive string output is great for debugging. Checking for symmetric layout direction is also helpful. This entire extension is nicely organized.


471-516: Convenient static constructors.
zero, all(_:), horizontal(_:), and vertical(_:) improve readability and usage clarity for typical spacing needs.


519-556: Additional text-related categories.
Defining category-specific enums (e.g., .edgeBelowText, .edgeRightText) is a neat way to keep specialized spacing rules well-structured.

Copy link

codecov bot commented Apr 6, 2025

Codecov Report

Attention: Patch coverage is 98.55769% with 3 lines in your changes missing coverage. Please review.

Project coverage is 21.44%. Comparing base (7f3ddeb) to head (a7ddcda).
Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
...rces/OpenSwiftUICore/Layout/Geometry/Spacing.swift 99.03% 2 Missing ⚠️
...tUICore/Layout/LayoutComputer/LayoutComputer.swift 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #245      +/-   ##
==========================================
+ Coverage   20.24%   21.44%   +1.20%     
==========================================
  Files         326      326              
  Lines       14609    14793     +184     
==========================================
+ Hits         2957     3173     +216     
+ Misses      11652    11620      -32     

☔ View full report in Codecov by Sentry.
📢 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.

@Kyle-Ye Kyle-Ye merged commit e88b997 into main Apr 6, 2025
10 checks passed
@Kyle-Ye Kyle-Ye deleted the feature/spacing branch April 6, 2025 17:12
@coderabbitai coderabbitai bot mentioned this pull request Apr 20, 2025
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.

1 participant