API <-> source rendering UX
In a discuss post, @dbuenzli suggested an alternative to the "Source" links that takes you from documentation to implementation:
The idea is to hyperlink the identifier (eg the x in val x : int -> int) instead of adding a new textual link (Source in val x : int -> int [Source]).
The advantage is: less things put on screen, nicer browsing once you know the feature. The disadvantage is less discoverability.
The linked post mentions another suggestion: that clicking on an identifier declaration in the source takes you to its documentation when it exists.
It feels natural to me:
- In the API docs clicking on a name generally leads you to its interface definition.
- If you click on the name of its interface definition it leads you to its implementation definition. [eg
xinval x : int -> int]- If you click on the name of its implementation definition it leads you to its interface definition. [eg
xinlet x i = i]
Thanks for opening the issue.
The linked post mentions another suggestion: that clicking on an identifier in the source takes you to its documentation when it exists
We may not have understood each other here. I don't think that clicking on identifiers in the source should go to the interface, I think we should mimick what merlin (half) does, that is go to the implementation and once you are on the implementation clicking on the name of the definition goes to the interface, and then on the interface back to the implementation in a wonderful infinite loop.
(it currently takes you to its implementation, staying in source rendering).
Currently these identifiers are not hyperlinked.
Ah, yes, indeed I misunderstood. Thanks for clarifying, I'll update the original post.
Note it would be possible to do what you suggested but my gut feeling is that most of the time it's going to be more painful if you browse the code for understanding.
That is given a clickable use of an identifier (here assumed to be a function) in the code these are the options:
-
- How does this function work: 1 click
- What's the signature or doc string of this function: 2 clicks
-
- How does this function work: 2 click
- What's the signature or doc string of this function: 1 clicks
-
More refined stuff like 1. or 2. depending whether the id is local to the module/library/package. Could be smart, but then you lose predictability.
Also one advantage of 1. is that it's more consistent behaviour: the signature may not exist if people eschew the .mli file.
If you use 2. then it's sometimes 1. when there is no .mli.
I really think that these links should always go to the documentation pages rather than to mli files. I agree that bouncing between interface and implementation is valuable, but the whole point of the documentation pages is to be an easier to read rendering of the interface, so the things you should bounce between are the documentation pages and the ml file. This also avoids the issue with there potentially being no mli file.
If you aren’t going to have links into the documentation pages from the source then I don’t really see the point of the source view: you might as well just send people to sources on GitHub.
I really think that these links should always go to the documentation pages rather than to mli files.
I don't think anyone suggested that. We are talking about bouncing between .ml renders and API doc pages here.
As I mentioned in the discuss post, there's not necessarily a one-to-one mapping between identifiers in the interfaces and implementations. It's quite possible to have an implementation that's exposed in multiples places in the interfaces, so we'd need to consider that, e.g. a pop-up when you click on it when there are multiple possibilities.
Do you have an example ? Is there perhaps a "more canonical" link ? (Also in a first implementation we can simply not link these cases and show in a tool tip that the backlink is ambigous).
A simple example would be an ml file like:
module A = struct let x = 10 end
include A
so you'd get 2 instances of val x : int with source links to the same place.
Well an example would need a concrete .mli file.
But if I imagine one for your particular example, there's clearly a "shortest path" which in this case would be MMM.A.x. Being in the implementation of MMM.A.x I would naturally expect to be brought there.
What could be confusing in using the "canonical" go to doc link, is that sometimes going to implementation then back to documentation does not takes you back where you started.
An example without canonical link could be:
(** x.mli *)
module A : sig
val f : int
end
module B : sig
val f : int
end
(** x.ml *)
module I = struct let f = 5 end
module A = struct include I end
module B = struct include I end
I.f has no canonical "go to doc", yet both A.f and B.f go to it (from documentation to implementation).
I suggest not to trip too much on this problem for now. I don't expect this to be the norm.
You can simply link to one and classify the identifier so that a visual cue can be added to warn the user about the fact that the backlink is ambiguous.