Releases: WendellXY/Description
Release list
0.3.0
Custom properties move to a new @DescribableProperties macro. This fixes a failure that 0.2.0 introduced on types whose Equatable conformance can't be synthesized. This release also removes optional-interpolation warnings from member-path placeholders.
.package(url: "https://github.com/WendellXY/Description.git", from: "0.3.0")Fixed
Equatablefailure with@Describable(0.2.0 regression). On a type whoseEquatableconformance can't be synthesized, such as an enum with a closure payload and a hand-written==, adding@Describablefailed with "type does not conform to protocol 'Equatable'" and the same==listed twice. The cause is a compiler bug triggered by macros that declare arbitrary member names, which 0.2.0 added so it could generate custom properties.@Describablenow declares only its fixed names, and the case from the report is kept as a regression test.- Optional-interpolation warnings from member paths. Placeholders such as
{locator.storeType}, and raw expressions such as{_0.productType}, no longer produce "string interpolation produces a debug description for an optional value" when the property at the end of the path is optional. The printed text is unchanged.
Breaking change
Custom properties (@Description("name", …) or .property("name")) now need @DescribableProperties next to @Describable:
@Describable
@DescribableProperties
enum Screen: AnalyticsNaming {
@Description("analyticsName", "chat_room")
case chat(roomId: Int)
}Without it, the compiler reports "custom description property 'analyticsName' requires @DescribableProperties", with a fix-it that adds the macro. Types without custom properties need no changes.
Requirements: Swift 6.0 or later, and swift-syntax 600 through 604. Tested on macOS and on Linux with Swift 6.0, 6.1, and 6.2.
0.2.0
@Describable now only turns synthesis on. All text comes from @Description, which can set the text for description, errorDescription, debugDescription, or a property of your own, and raw templates accept any Swift expression.
.package(url: "https://github.com/WendellXY/Description.git", from: "0.2.0")@Describable
@Description("User(id: {id}, name: {name})")
@Description(.debug, "User(id: {id}, name: {name}, tags: {tags.count})")
struct User {
let id: Int
let name: String
let tags: [String]
}
@Describable
enum Route: Error {
@Description("levelUpgrade(uid: {notify?.uid ?? 0}, hasReward: {notify?.reward?})")
case levelUpgrade(notify: Notify?)
@Description(raw: #"cart(active: {items.filter { $0.isActive }.count})"#)
@Description(.error, raw: #"{String(localized: "cart_failed", bundle: .module)}"#)
case cart(items: [Item])
}New
- Placeholder paths:
{info.redPacketId}, optional chaining ({notify?.uid}), literal defaults ({notify?.uid ?? 0},{id ?? "nil"}), and presence checks ({data?}, which renderstrue/false). The macro still validates each placeholder's first name, including spelling fix-its and actor isolation. - Raw templates:
@Description(raw: #"…"#)accepts any Swift expression in{…}, with the type's members and the case's associated values in scope (unlabeled values are_0,_1, …). Each expression must parse. - Targets:
@Description(.error, …),@Description(.debug, …), and@Description("name", …)/.property("name")set the text of one generated property..debugaddsCustomDebugStringConvertible. A custom name generatesvar name: String, for example to satisfy a protocol you declare on the type. Targets without their own text use the main text. @Describable(generating:)chooses which targets to generate, e.g.[.debug]for a type that should only beCustomDebugStringConvertible.@Describable(default:)sets the text of cases without a@Description:.caseName(the default),.rawValue, or.member("title").- Enum-level text: a
@Descriptionon an enum declaration applies to every case that has none of its own. - Diagnostics: the macro now also reports duplicate templates for one target, invalid targets,
.erroron non-error types (with a fix-it that addsError), invalid raw expressions, and existingCustomDebugStringConvertibleconformances or hand-written custom properties. The missing-template fix-it now inserts a memberwise@Description.
Breaking changes
| 0.1 | 0.2 |
|---|---|
@Describable("User({id})") |
@Describable @Description("User({id})") |
@Describable("…", error: "…") |
@Describable @Description("…") @Description(.error, "…") |
@Description("…", error: "…") on a case |
@Description("…") @Description(.error, "…") |
@Description(error: "…") on a case |
@Description(.error, "…") |
The generated text is unchanged for code that is migrated this way.
Requirements: Swift 6.0 or later, and swift-syntax 600 through 604. Tested on macOS and on Linux with Swift 6.0, 6.1, and 6.2.
0.1.1
Compile-time-validated descriptions for Swift enums, structs, classes, and actors.
.package(url: "https://github.com/WendellXY/Description.git", from: "0.1.1")@Describable
enum RequestState {
case idle
@Description("Loading {url}")
case loading(url: URL)
}
@Describable("HTTPError(code: {code})", error: "The request failed with HTTP {code}.")
struct HTTPError: Error {
let code: Int
}Features
@DescribablesynthesizesCustomStringConvertiblefor enums, structs, classes, and actors. It also synthesizesLocalizedErrorwhen the type listsErrorin its inheritance clause.@Descriptionconfigures individual enum cases. Cases without one are described by their name.- Templates support
{name},{0}, and{{/}}. Placeholders are validated during macro expansion. - Diagnostics point inside the template. Fix-its correct misspelled fields, escape stray braces, insert a memberwise template, and add
Errorconformance. - Actor descriptions are
nonisolated, and actor-isolated state is rejected at compile time. - Existing
description,errorDescription, and conformances are reported instead of overridden.
Changes since 0.1.0
- Added the MIT license.
- Added GitHub Actions CI, which runs the test suite on macOS and on Linux with Swift 6.0, 6.1, and 6.2.
- Made the test suite compatible with Swift 6.0.
- Documented a Foundation crash on Linux before Swift 6.2:
localizedDescriptioncrashes on any class-basedError, with or without@Describable. ReaderrorDescriptiondirectly, or use a struct or enum error.
No changes to the macros or their generated code.
Requirements: Swift 6.0 or later, and swift-syntax 600 through 604.