Skip to content

fix(commands): surface parse errors from #[command(...)] instead of silently dropping invalid entries #129

@RAprogramm

Description

@RAprogramm

Problem

`crates/entity-derive-impl/src/entity/parse/command/parser.rs:140` filters command-attribute parse results through `filter_map(...ok())`, which silently drops any `Err` from the parser. The behavior is documented as intentional ("Invalid commands are silently filtered out…") but it is a UX trap: a user who mistypes a `#[command(...)]` attribute sees no error and no generated method for that command. They just notice their command is missing at call site, far from the attribute that defined it.

This is the same class of bug fixed for `#[map(...)]` in #108 / #109. Apply the same pattern: surface the parse error as a `compile_error!` at the attribute site instead of swallowing it.

Fix

In `parser.rs` around line 140:

  • Replace the `filter_map(.ok())` with a collect over the iterator that preserves errors.
  • Collect parse failures into a `Vecsyn::Error`. After parsing all commands, fold them into a single `syn::Error::combine(...)` and emit it as a `compile_error!` token alongside the (successfully parsed) commands.
  • The successful commands continue to generate normally; the error tokens make the broken ones loud at compile time.

If only some commands are valid, we still want code generation to proceed for those — but the user must see a diagnostic for the broken ones. Compile-error tokens spliced into the generated module compile-fail-loudly, which is the desired outcome.

Tests

Two new trybuild fail cases under `crates/entity-derive/tests/cases/fail/`:

  1. `command_invalid_payload.rs` — `#[command(name = "Create", payload = "garbage $$ rust")]` produces a compile error pointing at the attribute.
  2. `command_missing_required_field.rs` — `#[command()]` with no `name` produces a clear "expected `name`" error, not silent omission.

Plus a unit test in `parser.rs` that asserts `parse_commands` returns the original errors when given malformed input.

Out of scope

  • Refactoring the command-attribute schema. Just propagate the errors the existing parser already produces.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions