the issue is not about multiple empty extension blocks, it’s about multiple extension blocks in general. it seems you believe there is no motivation for a module to ever provide more than one doccomment per external type (including types from the same package.) is this accurate?
No, that's not accurate. I think perhaps the many back and forth messages have muddled what I'm trying to get at. Let me start over—
To start, I think @ahti's post contains a key insight: extensions in Swift can be used for different purposes, and documentation comments attached to them can be used for different purposes also. For the purposes of this discussion, I think there are two key scenarios to consider, both of which are legitimate:
-
As you point out regarding new work implemented in Swift 5.9, a key use for extensions is to add new functionality to types defined in other modules; it makes sense that a user would want to present new information as part of the documentation of the extended type and that is indeed what @theMomax has implemented.
-
As @ahti points out, extensions are often used as a tool for grouping member declarations; it makes sense that a user would want to present new information about all of the members that are grouped together using a documentation comment attached to the relevant extension block.
There is absolutely nothing in the syntax of the language which allows an author to indicate which of these uses of extensions is relevant at any given point—and, indeed, these usages are not mutually exclusive. As I said in one of my earliest replies, it would be good to gather some empirical data regarding code "in the wild."
Supposing we were able to determine the author's intention to be exclusively usage (1), then it makes sense to present the documentation on the (extended) type itself, and some sort of way of sorting and concatenating multiple such comments together on the documentation page for said type is (or may be) needed. This, I believe, is what you're preoccupied with.
Now, contra your focus, @ahti asserts that the only use they could ever contemplate for documentation comments attached to an extension block are usage (2). This is certainly not generalizable to the entire Swift community, but to me it's a good signal that if usage (2) is not considered here, we are likely to run into scenarios such as what I illustrate in examples given in my first reply about actively misleading documentation.
Supposing we were able to determine the author's intention to be exclusively usage (2), then as @ahti says, it makes the most sense to associate the documentation with the members of the extension. If, as a matter of data presentation, this information cannot be shown just once next to a clearly demarcated grouping of members, the most appropriate fallback is to present the documentation as part of the documentation for each declared member. It would not make sense either to concatenate multiple such comments together in any order on the documentation page for the extended type, nor to prioritize one comment over another, in no small part because with usage (2) the contents of the documentation comment aren't (directly) about the extended type at all.
I think there are a few scenarios where authorial intention is abundantly clear:
You make a good point that there is nowhere to hang documentation about extensions for a type defined in another module except on an extension. Arguendo, one might naturally reach for something like a completely empty extension for that purpose. In that scenario where there's a single, empty extension of an external type with no constraints but with a documentation comment, I think we can be confident that the author intends for usage (1). I think the same conclusion can be drawn about a single, non-empty extension of an external type.
From the other direction, in the scenario where there are multiple extension blocks with the same generic parameters and conformances, all extending a type defined in the same module, but each with different attached documentation comments, I think we can be confident that the author intends for usage (2).
So, to come back to your question—do I think there will be scenarios that are in between these two poles? Of course! Even if they are rarer (which isn't salient to argue, and I don't), it would behoove us to discuss what the behavior should be. (I would suggest, for example, that there is much more "usage (2)-ness" than "usage (1)-ness" inherent to a scenario where multiple extension blocks with the same generic parameters and conformances, all extending the same type defined in a different module, each have different attached documentation comments.)
But for starters, my goal is to get us on the same page that (a) there are two broad categories of usages (which I've labeled as (1) and (2) above); (b) these are both legitimate usages we want to support; (c) they require different considerations when it comes to how and, crucially, where information is presented; and (d) there are at least a swath of scenarios where we can confidently infer the author's intentions.
Wdyt?
thanks Xiaodi, i think we’ve both been talking a bit past each other, this clarifies things a lot.
i think this argument is very compelling, but it has lost sight of what the extension block feature actually is at this point in time. to reiterate what @theMomax said, (in case it was lost) we only have information available about extension blocks that extend types external to the declaring module.
why does this matter? because it is currently assumed that extensions to external types make up a relatively small percentage of a typical project’s documentation, and the vast majority is still of the ordinary module-internal variety, which has no concept of extension blocks.
so i am reluctant to design a sophisticated system for curating and presenting documentation for groups of nested declarations that only works for module-external types, when it sounds like most of the motivation for extensions-as-groups is about documenting in-module types. the extent that we are considering in-module block-level documentation right now is mainly to avoid making any (more) choices that would block off this future direction.
i think it would be great if we had extension block information about all types in a module, and not just the external types. but this would require changes in the compiler (to lib/SymbolGraphGen), and it’s not something documentation tooling can implement on its own.
well, not quite. i’m experimenting with inferring implicit extensions for members of in-module types, because i’ve found it to be a really useful way to model symbol graphs. but those are implicit extensions, not implicit extension blocks - it is not possible to reconstruct the block-level information at this time.
Perhaps, reckoning purely on a quantitative basis, it will be predominantly "in-module" extensions that document groups of declarations using extension blocks, but as you say, the goal should be that choices now don't block off this future direction.
As I argue above, the two usages I outline aren't mutually exclusive—consider something akin to the Algorithms
package, for example: it would be entirely reasonable for a module that vends additional functionality for types that conform to standard library protocols to want to annotate groups of APIs in the same way as "in-module" extensions.
That 80% of what I call "usage 2" might be "in-module" extensions (for the sake of argument) doesn't mean that the other 20% of such usage is rare among "external-to-module" extensions—indeed, it is theoretically even possible that they could constitute the majority of documentation written about "external-to-module" extensions since we're talking about a totally different denominator.
okay, let’s break this down into a 2D matrix:
extends internal type extends external type
┌──────────────────────┬─────────────────────┐
extension-level │ supported │ supported │
documentation │ │ │
├──────────────────────┼─────────────────────┤
block-level │ not implemented │ implemented, │
documentation │ │ not supported │
└──────────────────────┴─────────────────────┘
i suppose we could speculate about the percentages in each cell, but honestly i don’t think that’s useful, and it sounds like you’re already convinced that all four cells are motivating, so let’s take that as a given.
today, there is no support for block-level documentation whatsoever, although @theMomax has unblocked quadrant IV, so support could be added, if we could ever nail down the rules for external block-level documentation.
i guess the question is now: what should be the default, and how will users opt-in to the mode that is not the default? and looking forward, if we ever do get around to block-level documentation for in-module symbols, should the default be the same for both kinds of extended type?