Let a method returning an ExecutableResult document its outputs in @return

This is a follow-up from #3518120 (closed) and the legendary !162 (merged).

A tool method that returns a plain value gets its outputs 'for free' from the return type.

As soon as it returns an ExecutableResult, because I often want my own message or a FailureCategory, that's gone and I have to write every output by hand with #[ToolOutput(data_type: ...)].

Value objects aren't normalized either, so I do that myself too.

This came to my attention while building my booking tool (cfr. https://fonsvandamme.com/book-a-call).

Adding a nicer failure message meant rewriting all the outputs.

Proposed resolution

No new attribute argument, just a generic docblock:

/**
 * @return \Drupal\tool\ExecutableResult<array{year: int, albums: list<\Drupal\album\Album>}>
 */
public function albumsOfYear(int $year): ExecutableResult {

The type between the brackets is read exactly like a plain return type, so this gives a year and an albums output, and the Album objects get normalized. ExecutableResult gets @template T so PHPStan is fine with it.

Without the docblock nothing changes.

I have it working locally with tests, MR coming.

Remaining tasks

  • MR with tests
  • Update "Returning an ExecutableResult" in docs/developers/tool-methods.md

Related: #3583100 (same docblock parser).

Yes, this issue was drafted with the help of AI (structure), but I've read and reviewed it and I stand behind it.

Edited by Fons Vandamme