Skip to content

0.2.0

Choose a tag to compare

@WendellXY WendellXY released this 25 Sep 05:08
· 3 commits to main since this release

@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 renders true/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. .debug adds CustomDebugStringConvertible. A custom name generates var 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 be CustomDebugStringConvertible.
  • @Describable(default:) sets the text of cases without a @Description: .caseName (the default), .rawValue, or .member("title").
  • Enum-level text: a @Description on 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, .error on non-error types (with a fix-it that adds Error), invalid raw expressions, and existing CustomDebugStringConvertible conformances 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.