Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Links in type signatures #3471

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

joshi-monster
Copy link

@joshi-monster joshi-monster commented Aug 1, 2024

I feel like this has already gotten quite big, so I thought I'd stop at the early point before you say it's all unreasonable anyways and I waste a bunch of time :D

First: I cannot "just" generate links, since highlight.js will not allow them..

Instead, all code relevant to type/function/constant signatures is highlighted at compile time, and types are always printed using the type_::pretty::Printer in the docs. It introduces a new variant to the Document, and a new DocumentWriter trait that can react on them. Since it looked like the documents formatter goes to great length to avoid being recursive, I've also tried to do that. This introduces another new Cmd type that gets used instead of the list of (indent, mode, doc) triples, and consequently changes a lot of types around in format. Just doing recursion would basically get rid of all of that.

Overall, this allows for all signatures (with small extensions all parseable Gleam code) to be highlighted by the compiler directly, without relying on Javascript. This could potentially also be used to add colors/links to error messages, or annotate all examples in the docs as well.

If a resolved type (ignoring aliases) is publicly exposed, a link to its documentation will be generated as well. Versions are currently ignored. Ignoring aliases means that a common pattern doesn't work currently (lustre for example does this with every type), where an internal type is re-exported using a type alias.

Questions

  • What about tests? There are existing tests for the docs output which I updated, but generally, I'm a bit lost what you would expect.
  • What to do about the alias thing?

fix #3461 #828

Annotated documents allow putting a class, and optionally a link and hover text around another document.
We cannot use highlight.js' syntax highlighting anymore if we want links, since highlight.js will strip all existing markup from <code> blocks for XSS reasons. (see https://github.com/highlightjs/highlight.js/wiki/security)
This mechanism will be used to annotate expressions/tokens during pretty printing, allowing us to implement our own syntax highlighting inside of the pretty printer.

Extend Utf8Writer to DocumentWriter, which has enter/exit callbacks whenever annotations are discovered
Implement HtmlWriter which prints hljs-* span tags or links

Extends the command queue for fit/pretty to include `AnnotationExit` to keep the spirit of avoiding recursive calls.
- use the new annotations to be able to highlight types using the type pretty printer, as well as the type_ast in the format
- a new docs_* functions to the formatter that print using the type_::pretty::Printer instead of the type ast
- output signatures in the docs as raw HTML, disabling highlight.js for them
Copy link
Member

@lpil lpil left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

We don't want to modify the formatter at all for this. As the comment on the documentation generation code says we want to stop using the same code for both, so this would be the point where we split it so we can have two specialised bits of code rather than 1 lowest-common-denominator.

The pretty module must not know anything about Gleam or HTML or code, so the annotation and to-html method must be removed. The thing to add is a ZeroWidthText which would work the same as text but have contents which do not contribute to the size. This would be a very small change to the code.

Loops are used over recursion as Rust doesn't have TCO so the printer would (and used to!) crash if recursion is used.

The tests as you have them look great!

@joshi-monster
Copy link
Author

joshi-monster commented Aug 26, 2024

Thank you so much for taking a look at this! I kind of put this on hold, since I wanted to wait what your thoughts in the discussion thread were first 🙂

I had a version with a ZeroWidthString constructor at first but decided against it, since it would have added very HTML/doc-specific things to the formatter. I also unfortunately didn't see the comment, sorry. I ended up with those annotations since they were kind of general (following the highlight.js classes) and allowed me to experiment with syntax highlighting in the CLI output 😄

A special formatter for printing docs and a ZeroWithString would also solve this, and be indeed a much smaller change to the the pretty module, I'll do that then instead!

I understand why the loop is done this way; I just felt like for sure noone is gonna stack-overflow with the depth of the tree 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

(hex)docs: types in function signatures should be clickable links to their documentation
2 participants