Detect single-line previews like #Preview("x") { foo() }#166
Conversation
Single-line previews whose closure opens and closes on the same line as the #Preview macro were silently skipped, so no snapshot test was generated for them. Two issues, both fixed here: - PreviewLoader.previewBodies started tracking the brace balance only when a line had a non-zero brace change. On a single-line preview the opening and closing braces cancel out (braceChange == 0), so the balance was never initialised and the body was never collected. It now starts tracking as soon as a line contains the opening brace. - RawPreviewModel.init derived the first line via `dropLast(2)` + `removeFirst()`, which traps on a single-line body (the collection is empty after dropLast(2)). It now takes the first line directly; the body and properties are already parsed from the full macro body via SwiftSyntax, so nothing else is affected. Adds unit tests for both code paths.
|
@AllDmeat Hi! Thank you for improvements. This fixes the single-line case, but it also makes extraction depend on any For example this now gets truncated to only the first line: #Preview("{braced}")
{
Text("TestView")
}Previously this worked because |
The line-based brace scanner miscounted braces inside string literals,
comments and raw strings, truncating previews like `#Preview("{braced}")`.
Locate macros with SwiftSyntax so the real source range is always correct.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Good catch, thanks. Switched the extraction to SwiftSyntax as you suggested — Added a regression test for your counterexample: #Preview("{braced}")
{
Text("TestView")
}All existing single-line/multi-line/Allman/ |
|
Super, thanks for the enhancement! |
Problem
Single-line previews whose closure opens and closes on the same line as the
#Previewmacro are silently skipped — no snapshot test is generated for them:There is no warning or error; the preview simply never produces a test.
Root cause
Two spots, both needed for the case to work end to end:
PreviewLoader.previewBodiesstarts tracking the brace balance only once a line has a non-zero brace change (braceChange != 0). On a single-line preview the opening and closing braces cancel out (braceChange == 0), so the balance is never initialised and thebraceBalance == 0close condition never fires — the body is never collected.RawPreviewModel.initderives the first line viadropLast(2)+removeFirst(). For a single-line body the collection is empty afterdropLast(2), soremoveFirst()traps.Fix
previewBodiesnow starts tracking the brace balance as soon as a line contains the opening brace, regardless of whether it nets to zero on that line.RawPreviewModel.inittakes the first line directly. Thelinesslice afterremoveFirst()was never used — only the first line matters here (fordisplayName/traits);bodyandpropertiesare already parsed from the full macro body via SwiftSyntax, so nothing else changes.Multi-line previews are unaffected: their
#Preview {line already has a non-zero brace change, so balance tracking starts exactly as before.Tests
PreviewLoaderTests: single-line only, single-line + multi-line mixed, and single-line underdefaultEnabled: false.RawPreviewModelTests: single-line body parsesdisplayName,body, andtraitscorrectly.Full
PrefireExecutablesuite: 45 tests, 0 failures.