Skip to content

Changes from Swift-App-Template#125

Draft
leogdion wants to merge 1 commit intov0.0.4from
swift-app-template
Draft

Changes from Swift-App-Template#125
leogdion wants to merge 1 commit intov0.0.4from
swift-app-template

Conversation

@leogdion
Copy link
Copy Markdown
Member

@leogdion leogdion commented Apr 2, 2026

No description provided.

feat: Swift App Template v1.0.0-beta.1 (#11)

- Copy and restructure MonthBar infrastructure into template layout
- Replace all hardcoded values with `{{TEMPLATE_*}}` placeholder tokens
- Add `Packages/TemplateGenerator` — Swift executable that generates app skeleton files using SyntaxKit
- Add `Scripts/setup.sh` — interactive/automated setup with 19 token substitutions, Swift file generation, CI activation, full-stack mode, cleanup, and git reset
- Add `README.md`, `README.template.md`, and `CLAUDE.template.md` template documentation
- Move `workflows/app.yml` → `.github/app.workflow.yml` so GitHub skips parsing it until `setup.sh` activates it
- Add `.github/workflows/validate-template.yml` — CI that confirms placeholder tokens haven't been replaced on the template repo
- Replace placeholder-specific icon assets with a generic gradient placeholder
- Sync `_reference/MonthBar` to latest upstream
- Add `_reference/AtLeast` — iOS/watchOS companion app reference with multi-platform Fastlane and dynamic CI matrix
- Extract `private_lane :setup_api_key` in Fastfile; add `sync_build_number`, `sync_last_release`, `upload_metadata`, `upload_privacy_details`, `submit_for_review` lanes
- Add `pull_request` trigger, concurrency group, and dynamic matrix to CI workflow
- Split `build-macos` into always-run and full-matrix jobs; gate Windows/Android on cross-platform condition
- Add conditional server test jobs wrapped in `FULL_STACK_ONLY` markers for `setup.sh` processing
- Bump actions: `checkout@v6`, `swift-build@v1.5.2`, `swift-coverage-action@v5`, `codecov-action@v6`, `mise-action@v4`
- Prefix all Makefile `fastlane` calls with `mise exec --`; add screenshot targets
- Expand CLAUDE.md Commands and Code Signing sections with new Fastlane lanes and make targets
- Add automation guide TODO tracker linked to issues #28#50
- Fix `bundle install` and git section in `setup.sh`; harden with `printf -v`, required-field validation, and `swift` availability check
- Replace `keywords.txt` with lorem ipsum placeholder to force users to update before App Store submission
- Bump Dockerfile base image from `swift:6.0-jammy` to `swift:6.3-noble`
- Add `client` to `openapi-generator-config.yaml` generate list
- Remove LFS exclusion section from `.gitattributes`

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 2, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d01f23d3-a2cc-4a47-a10c-16381ac05ca5

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch swift-app-template

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@leogdion leogdion marked this pull request as draft April 2, 2026 15:13
@claude
Copy link
Copy Markdown

claude bot commented Apr 2, 2026

PR Review: Changes from Swift-App-Template

Thanks for the additions! This PR brings several useful features: access modifier support for Class, Function, and a new Initializer type; IfCanImport for conditional compilation blocks; and a buildAttributeArgumentExpr helper for proper string-literal attribute arguments. Overall the approach is sound and fits the existing patterns well. A few things worth addressing:


Bugs / Correctness

1. Initializer has no parameter support (significant limitation)

Initializer.swift hardcodes an empty parameter list:

parameters: FunctionParameterListSyntax([]),

This means every generated init will always be init(). Real-world initiailzers almost always have parameters. This should either be implemented before merging or explicitly noted as a known limitation with a follow-up task.

2. buildAttributeArgumentExpr string detection is fragile

if argument.hasPrefix("\"") && argument.hasSuffix("\"") && argument.count >= 2 {
    let content = String(argument.dropFirst().dropLast())

This heuristic fails on:

  • "hello"world" — treated as a string literal with content hello"world
  • "\"" — content becomes \" rather than the escaped quote character
  • Strings that are exactly "\"" (a string with one double-quote char)

A more robust approach would be to use String's initializer from a Substring after checking that both the first and last chars are " and the inner content doesn't contain unescaped quotes, or alternatively accept typed arguments (enum AttributeArgument { case identifier(String); case string(String) }).

3. Force unwrap in testPublicFinalClass

let publicRange = generated.range(of: "public")!
let finalRange = generated.range(of: "final")!

Force unwrapping in tests causes a crash rather than a clean test failure. Prefer:

let publicRange = try #require(generated.range(of: "public"))
let finalRange = try #require(generated.range(of: "final"))

Code Quality

4. open + final combination is not guarded

Class now allows .access(.open).final(), which produces open final class — invalid Swift (the compiler rejects it since open is the opposite of final). Consider either adding a runtime assertion or documenting this as a caller responsibility.

5. Inconsistent trivia fix for Import vs other declarations

Import.swift correctly uses .space (so @testable import gets the right spacing), while all other declarations use .newline. This is intentional and correct, but the asymmetry is easy to get wrong for future contributors. A brief comment explaining why Import differs would help.

6. Non-deterministic test assertions in AttributeTests

#expect(generated.contains("@Suite(\"App Model\")") || generated.contains("@Suite( \"App Model\")"))

The || suggests the output format isn't stable. Tests should assert one exact form; if there's a formatting choice, make it deterministic in buildAttributeArgumentExpr.


Missing Coverage

7. IfCanImport has no tests

The new IfCanImport type has zero test coverage. At minimum, a test asserting that:

IfCanImport("Foundation") { Import("Foundation") }

produces:

#if canImport(Foundation)
import Foundation
#endif

would prevent regressions.

8. No test for async + throws Initializer

testThrowingInit and testAsyncInit exist, but there's no test for .async().throwing() combined on an Initializer, which exercises the effectSpecifiers path more fully.


Minor

  • IfCanImport.swift and Initializer.swift use public import SwiftSyntax while AttributeArgument.swift uses import SwiftSyntax. Given neither exposes SwiftSyntax types in their public API, the public qualifier is unnecessary on the imports in those files (though following existing codebase convention is fine if that's the pattern elsewhere).
  • Function.throwing() just calls \throws`()` — the backtick call site is fine internally, but the alias is a good ergonomics addition for callers.

Summary

Severity Issue
🔴 Major Initializer missing parameter support
🟠 Medium buildAttributeArgumentExpr fragile for edge cases
🟠 Medium No tests for IfCanImport
🟡 Minor Force unwrap in testPublicFinalClass
🟡 Minor open + final combination not guarded
🟡 Minor Non-deterministic `

The access modifier work and the throwing() alias are clean. The biggest concern before merging is the parameterless Initializer — if it's intentional (MVP), it should be tracked explicitly.

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 2, 2026

Codecov Report

❌ Patch coverage is 69.79866% with 45 lines in your changes missing coverage. Please review.
✅ Project coverage is 79.35%. Comparing base (18c1e25) to head (d680855).

Files with missing lines Patch % Lines
Sources/SyntaxKit/Declarations/IfCanImport.swift 0.00% 32 Missing ⚠️
Sources/SyntaxKit/Declarations/Enum.swift 0.00% 3 Missing ⚠️
Sources/SyntaxKit/Declarations/Extension.swift 0.00% 3 Missing ⚠️
Sources/SyntaxKit/Declarations/Protocol.swift 0.00% 3 Missing ⚠️
Sources/SyntaxKit/Declarations/Import.swift 33.33% 2 Missing ⚠️
Sources/SyntaxKit/Declarations/Initializer.swift 96.55% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           v0.0.4     #125      +/-   ##
==========================================
+ Coverage   77.98%   79.35%   +1.37%     
==========================================
  Files         126      129       +3     
  Lines        5651     4685     -966     
==========================================
- Hits         4407     3718     -689     
+ Misses       1244      967     -277     
Flag Coverage Δ
spm 79.03% <69.79%> (+1.47%) ⬆️
swift- 79.35% <69.79%> (+1.40%) ⬆️
ubuntu 79.35% <69.79%> (+1.40%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ 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.

public import SwiftSyntax

/// A Swift `init` declaration.
public struct Initializer: CodeBlock, Sendable {
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

don't we already have this?

public import SwiftSyntax

/// A `#if canImport(Module)` … `#endif` conditional compilation block.
public struct IfCanImport: CodeBlock, Sendable {
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

don't we already have a pound #?

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