Documenting Fusion

I think it would be helpful to not only show small examples, but take an almost real world prototype with 10 props or something and add all annotations.

When I read through the various proposals, some look good to me for small components (co-locating prop and docs), some would probably work much better with complex ones (grouping the docs).

Besides generating documentation, the target user to read those annotations would be someone who wants to quickly browser a prototype and understand its behaviour without reading the whole file, right?

Another important part is which version is easier to keep up-to-date when the component evolves over in a project over months and years.

4 Likes

After some discussion these are the two (and a half) proposals. Each has some pros and cons which will be assest later.

1. @doc

The original proposal. Based on the existing @propTypes idea and formatting

1.5 @doc rearranged

Essentially the same as the original proposal. But now the types and summaries are next the properties instead of being grouped together. (Some syntax highlighting is added as well)

2. Comments

The other proposal is to use comments as a semantic way to add documentation.
(This has complete syntax highlighting applied)

Notes

Beware that full syntax highlighting and completion will be added to the final proposal regardless which will be chosen. The highlighting in the examples is just to get some feel for it.

Also keep in mind that color and styling is fully depending on the theme:

Thank you for this summary!

Bit meta thought but I guess we wouldn’t want to add parsing of the comments to fusion, so doing it that way will make the docs forever hidden for the fusion runtime. I could totally see a use for having access to it at runtime to eg. provide more helpful error messages, enable property type inspection and stuff like that. Which to me says option 1 or 2,

I just wonder if either way we should only use a single top level meta property (so eg. have everything under @doc as it might as well be @doc.types.request ?

Thanks a lot for the summary, that makes the whole topic much more accessible!

I agree to @christianm’s comment. Parsing comments feels like a step back to PHP 5 times :slight_smile:

There are three “issues” I currently have with the other suggestions:

1. Why are the docs part of the type meta information?

Why not, instead of

    action = null
    @types.action = 'string'
    @types.action.@doc = 'some docs'

Something like this:

    action = null
    @types.action = 'string'
    @docs.action = 'some docs'

2. Co-location

I prefer the syntax of 1.5 because it keeps props and their type/docs close together.
And probably something like this is not possible:

    action = null
    action.@type = 'string'
    action.@doc = 'some docs'

right?

3. @doc has different shapes

In your example @doc is sometimes just a string and sometimes an object with summary and description – this is at least slightly misleading and potentially error prone

Technically we could apply the meta to any fusion path, collecting them becomes a bit more complicated but it shouldn’t be a big deal and I like that idea.

I just wonder what happens if you set/override the prop from the outside, also it will suddenly be part of the prop (meta) value.

Is that an issue?

As long as you don’t > the prop the meta should stay intact, and yes indeed it becomes part of the prop value but anything we do in fusion should be able to deal with arbitrary meta props, the only thing is, if your property is a fusion object you now have a meta @type on it that is actually from the parent prototype (it’s localised so not a big deal but might be a bit weird)

1 Like

The reason to not use path.@type and path.@doc during the last discussion were that @type suggests type safety while it „only“ is a documentation feature (at least for now).

If we go the @type way we should define the allowed values carefully. I personally would understand the @type as the type after the full evaluation of the fusion path including all processors.

On 21.12. we discussed this matter for a few hours and i threw in the idea of using comments - which i still prefer most. I noted a few arguments for and against the use of comments which i later refined:

Fusion documentation via comments

1.1 :green_circle: visually easy to read and understand when viewing the sources
1.2 :green_circle: pleasant to look at (especially with syntax highlighting)
1.3 :green_circle: one might be able to apply their knowledge from php doc and it feels more familiar
1.4 :red_circle: documentation syntax (if not validated strictly) is in complex cases try and error and thus a bad dx
1.5 :orange_circle: requires adjustment on the parser who should generate the RST docs - doesnt have to be in php land as we can also extend Simons javascript fusion parser.
1.6 :green_circle: does not appear in regular merged array tree as __meta field.

  • might possibly under a special __documentation key
  • i think this distinction is important to make as approaches like @doc use the meta syntax which currently always influences runtime behavior. Using __meta because is simpler and already available should not blinden our judgement. I think there is no reason to have the documentation available semantically for the runtime as __meta field. And using the meta might only lead to confusion (see 2.7)

1.7 :orange_circle: inheritance works only partially out of the box and is not that delicate and has to be implemented and carefully though of

  • for example partially overriding only the type or description of a path is not possible, the whole path has to be duplicated.
    • i’d argue that this is (hopefully) hardly a usecase, but we have to see and try this on real world fusion.

1.8 :green_circle: comments are already used in projects to document fusion and it should be ideal to simply migrate them
1.9 :green_circle: comments are always understand as optional by every developer which is important, so its imminent that they can be deleted and that their type information is totally optional and will not in any way influence the execution.

Fusion documentation via meta paths like @doc or similar

2.1 :green_circle: no change in fusion parsers as it’s simply parsed already
2.2 :green_circle: easier to build tools for validation and rst doc generation
2.3 :orange_circle: precise but complex structure (with the different @doc paths one can mixup)
2.4 :red_circle: visually imo too complex, bloated and not as easy to read and understand when viewing the raw fusion sources
2.5 :red_circle: semantically i think it’s wrong to misuse the merged array tree for doc information (see 1.6)
2.6 :green_circle: inheritance and partially only overriding a type of a path is flawlessly possible
2.7 :red_circle: new comers might not understand that the documentation via meta path is totally optional as other meta properties always influence runtime behavior, so i would expect to see bad copy pasted code.

  • Also the type information could be misinterpreted as validated. In my opinion we should not mix type documentation and actual type hinting, which might be used for runtime checking like in php.

Both approaches share this common downside:

  • :red_circle: special complex niche syntax (additional properties like [key] for a join) might be not obvious and hard to find out and use

Discussions


And i personally think that this is a good thing as stated in 1.6. If we would like to mimic phps behavior to have reflection for comments/documentation, we can archive this by saving the documentation in a new dedicated __documentation field in the merged array tree.
Having the property type available at runtime will be important once we introduce proper types. But as i wrote in 2.7 i think we should not mix documentation and real types. Also in php the doc type is not available directly via reflection as one needs to parse the comment first.


And i personally would strive away from mixing documentation types and real types (see 2.7). So if we decide for the use of the meta documentation and a dedicated @types path, while pretty. it would only pretend to have real functionality.


I can only say that comments even though types like in modern php or with typescript exist are still important and personally the prettiest way to document the behavior.

2 Likes

I agree to using comments, but I would suggest to omit type information in them (but that is up to the implementer of course).

In fact, that’s the syntax I use in my components already most of the time (see example) – I just used # instead of /// to start an inline comment – but I’m happy with both

Type…hinting

I vouch strongly for keeping type information in the documentation as it is needed to fulfil the main goal…the substitution of the hardcoded Neos Fusion Reference.

But i think we should call them type hints from now on and everywhere :D just to make sure they are not understood as “real” types…So i vouch for keeping the type hints.

/// or #

Using # for the documentation was an idea as well. But that would mean to completely change the usage of an existing token which is not ideal.
/// stems from Rust where it is already used for documentation. (and i personally do not like the # comments but that would be too opinionated to even mention it sooo…)

/// also follows the same idea as the PHP attributes #[foo] where an existing single line comment has another completely different meaning because of its next character.

So conceptional /// is not a "single line comment token with a following / ". It is the “property documentation token” and /** & **/ are not a “multiline start and end tokens” but “prototype documentation start and end tokens”. Just by a “great coincidence” the existing fusion parser interprets them as comments. Or should i say the existing fusion parser implementation interprets them as comments? …foreshadowing…

Even better ?

@Marc and i tested a few other ideas like using ```doc or /*doc for prototype docs etc. but they all seemed too clunky to write and looked kinda weird.
But if there are any other ideas please feel free to throw them into discussion!

Next steps

Currently my favourite is using /// and /** **/ instead of @types and @doc. With proper syntax highlighting the code looks like a document which you can read. It is easier to parse visually. It just looks nice.

prototype(Foo.Bar) {
    /// string The title above the text
    title = "bar"
}

But if we would use @typeHints instead of @types we would not make false promises and do not a give false sense of (type) safety:

prototype(Foo.Bar) {
    title = "bar"
    @typeHints.title = "string"
    @doc.title = "The title above the text"
}

OR…because no abbreviations…

prototype(Foo.Bar) {
    title = "bar"
    @typeHints.title = "string"
    @documentation.title = "The title above the text"
}

So when we would introduce “real” type a simple search @typeHints & replace with @types would be quite nice.

End note

Would it make sense to start a vote between the general idea of using something like /// and using something like @doc ?

Because where the data of @doc gets stored (in _meta or in _documentation) or if we use # instead of /// are subtleties in my opinion.
Everything after /// (or #) would not be text but its own very small documentation language and where or even if that is stored has nothing to do with how it is written. The same goes for @doc. Both of them could land inside _documentation in the merged array tree or not at all.

The general idea is to separate language specification from implementation. The specification can be opinionated by the implementation of course…but still.

A future specification could introduce “real” types and /// would then be used only for text:

prototype(Foo.Bar) {
    /// The title above the text
    title: string = "bar"
}
2 Likes

Aaand we should have a way to mark fusion objects as internal like

/** @internal */ :wink:

I think that is similar to the typing “problem”. As long as we can not guarantee that an “internal” object is not used “outside” we should not call it internal but something that transfers the idea of “should not be used outside”. And i think just using “Internal” as part of the prototype name works quite well.

Recap

The current Fusion Reference is built using hardcoded templates. The goal of this proposal is to move the documentation into the code to generate the Fusion Reference straight from the code and to improve the Developer Experience (IDE support etc.).

Options

We are currently at the point where there are two main choices for how fusion can be documented. Either using some kind of properties (1.) for the “fusion-way” or using some kind of comments (2.), as other programming languages do.

Syntax highlighting for better readability and adaption will be provided either way.

The styles of comments, syntax within these comments, and the specific meta properties to be used are not part of this poll.

The same goes for type hints; how and whether we want to incorporate type hints and to what extent should also not influence the decisions.

1. @doc

Documenting prototypes and properties using some kind of @doc meta tags.

For example:

2. ///

Documenting prototypes using some kind of multiline “comments” (e.g. /** **/) and properties with single line “comments” (e.g. ///)

For example:

Poll

How should we document fusion?

  • 1: @doc - Metaproperties
  • 2: /// - Comments
0 voters

In optin 2 you mean Documenting prototypes using some kind of multiline “comments”, I assume?

Ah yes, of course!

The poll results aren’t clearly favoring any particular solution. Should we extend it to the Slack Announcements channel to gather more comprehensive feedback, or should we reconsider our approach to find a solution that gains broader support?

1 Like

Why not? OTOH we have a 56% vote in favor of the comments syntax. So if you’re up for it, you could IMO just go ahead and implement that :slight_smile:

1 Like