rescript-compiler icon indicating copy to clipboard operation
rescript-compiler copied to clipboard

Automatic Documentation Generation

Open leostera opened this issue 5 years ago • 12 comments

Opening this issue for tracking purposes and discussion 🗣

Context

Documenting a project that builds with bsb right now is a fragmented experience. You can use:

  1. docre/redoc,
  2. you can manually drive odoc from the terminal or with a script,
  3. you can use bsdoc, or
  4. you can even set up a dune project around your sources so it compiles the documentation for you.

I believe this, among other reasons, to aid in the scarcity and scattering of documentations for libraries in the wild. If bsb worked with a blessed documentation tool out of the box, we could get several benefits in the small, and in the big.

In the small, people writing docs will get a consistent experience when documenting. No longer having to go around asking "What can I use to document?" and consolidating both knowledge and docs styles across the community.

In the big, complete catalogs of documentation for packages can be generated since they all work with the same tool — imagine Rust docs (https://docs.rs), or Hoogle (https://www.haskell.org/hoogle) but for Reason/BuckleScript.

odoc

odoc has established itself as the documentation tool for the OCaml ecosystem, with first class support from dune, and a number of auxiliary tools around it (such as odig). It is in heavy industry usage, has a sophisticated cross-referencer, and has been backported to work with OCaml 4.02.3+buckle-master. This meant we can start using it with BuckleScript.

However, because odoc is a low level tool, it requires orchestration, which led me to create a package that does such orchestration for you:

MyProject $ yarn add bsdoc --dev
MyProject $ yarn build

 MyProject $ yarn run bsdoc support-files --output-dir=./docs
yarn run v1.12.3
$ ./node_modules/.bin/bsdoc support-files
info: Copying support files (CSS, JS) into ./docs
info: Done ✅
✨  Done in 0.60s.

 MyProject $ yarn run bsdoc build MyProject
yarn run v1.12.3
$ ./node_modules/.bin/bsdoc build MyProject
info: Compiling documentation for package "MyProject"...
info: Generating .html files...
info: Done ✅
✨  Done in 0.45s.

bsdoc simply orchestrates calls to odoc. Which means it on a working version of odoc available, which it turn requires the right opam switch with the package installed.

So there we have it:

[ build-tool ] --orchestration--> [ odoc ]

Proposal

I'd like for the bs-platform to support the following use-cases:

  • [ ] New project should always be documentation-ready
  • [ ] In watch mode, saving a file should update the documentation (and show any warnings if the documentation is broken: e.g., a type was renamed in a module, but not in the docs)
  • [ ] When only building once, all necessary documentation should be generated
  • [ ] It should be possible to regenerate the support-files without starting a new project / copy pasting from another place

I do not include locally serving documentation as a use case, given the ubiquitous nature of static file servers that people can use for it.

To support those use-cases, I'd like the bs-platform package to include:

  • odoc in some shape of form, perhaps as a binary,
  • bsdoc to setup support files (theme, js, etc), building the whole documentation, and future workflows
  • bsb to include rebuilding documentation on every compilation unit change.
  • bsb -init template to include documentation setup

Naturally, this last list is much less important than catering for the use-cases of the first one. So it matters less to me that we have a binary odoc, or that we include bsdoc at all. We could perhaps bundle both into bsb and that should be okay too.

/cc @bobzhang @rizo @aantron


Relevant Issues

https://github.com/ocaml/odoc/issues/209 — In the past we've seen problems with automatic namespacing. This could mean making BuckleScript namespacing valid OCaml namespaces. Something to figure out.

https://github.com/ocaml/odoc/issues/275 — @nikgraf has raised that the external keyword output needs improvement.

leostera avatar Dec 10 '18 13:12 leostera

Thanks @ostera!

I just wanted to state that we are interested in providing first-class support for Reason syntax. In fact I'm currently working on integrating odoc with Reason+esy projects (https://github.com/esy-ocaml/hello-reason/issues/13).

Let me know if there's anything I can help with.

rizo avatar Dec 10 '18 18:12 rizo

Crosslinking external output issue from odoc here: https://github.com/ocaml/odoc/issues/275

leostera avatar Jan 08 '19 18:01 leostera

I've spent the last few days investigating how we can embed odoc into bs-platform.

The two approaches I've listed down are:

  1. Embed as a single file, in the same spirit as refmt is embedded,
  2. Build with esy

1. Embed as a single file

This would clearly be "easier", given that the approach is already in use in the bs-platform, and is the option that would have the least impact in dependencies of bs-platform overall.

Unfortunately, some idiosyncrasies from bspack do not let me pack the dune project easily. I've gone down a rabbit hole of module renaming and library packaging, but it did not yield good results. Mostly due to bspack not following dune conventions, which is unfortunate.

Roughly speaking, duplicate modules, and the automatic namespacing that dune features break bspack.

To proceed with this I'd have to adapt bspack to understand these dune conventions and make it possible to pack odoc automatically (so updating it isn't a slow, error prone, manual chore).

As an advantage, other projects may also be easy to pack and include with bs-platform.

2. Build with esy

Alternatively, given that BuckleScript is already using esy, we could include the esy toolchain as part of the bs-platform build step. This would allow us to build odoc verbatim from source.

It would also serve as a platform for building bs-platform with esy, slowly getting rid of the ad-hoc build tooling it currently has.

I'll start looking into this now to see what needs to be done there.


Any thoughts?

/cc @bobzhang @chenglou @nikgraf @ryypyy

leostera avatar Feb 13 '19 10:02 leostera

After exploring more building with esy, we'd need:

  1. To bake an esy binary into bs-platform, which may not be ideal.
  2. Include a odoc.exe target into lib/body.ninja that shells out to esy to build everything in isolation, and copy the executable back.

I haven't looked at how to preserve the paths to the static files that odoc expects, but this could be trivial (place them by the executable), or can be fixed in odoc by crunching the assets into an ML module.

Currently talking to @jordwalke about 1 again.

leostera avatar Feb 13 '19 11:02 leostera

Note we don't depend on esy. In the short/mid term, bs-platform will be self-contained. One thing worth exploring is to make bspack more capable to pack those stuff

bobzhang avatar Feb 13 '19 19:02 bobzhang

@bobzhang can you ellaborate on bs-platform being self container?

leostera avatar Feb 13 '19 21:02 leostera

Could there be a possibility of splitting out a BuckleScript-compatible odoc into a separate npm package, e.g. bs-platform-odoc? Then we could modify the project templates to create projects with that (dev) dependency and a run script e.g. npm run doc that calls that package's odoc.

yawaramin avatar Feb 14 '19 01:02 yawaramin

@yawaramin we could pack odoc for npm consumption. It is doable, we just haven't done it. There's 2 arguments to be made against it.

Firstly, odoc needs to be compiled with a matching version of the compiler you are compiling your project with. This means the versioning of the npm package will have to include the version of the compiler as well.

That is, if you are using BuckleScript 4.0.18, which builds on OCaml 4.02.3+BS, you need odoc compiled with OCaml 4.02.3+BS. Like in yarn install [email protected]+BS where 1.3.1 is the odoc version.

If you update to a newer version of BuckleScript, 5.x, that builds on OCaml 4.06+BS, you'll need a different version installed.

Because of this, I think a better developer experience, that prevents compiler mismatches and package version headaches, bundles and builds odoc with whatever compiler is shipped in the version of bs-platform that you are using.

Secondly, we want to introduce documentation flows to the standard bsb build flows. To do this, bsb must be able to invoke odoc reliably as part of the build process, and packing it would let us do tighter integrations.

If the internals of bsb change so that artefacts (.cmti files, etc) are stored somewhere else, then the odoc package on npm, which was expecting artefacts to appear in a particular place, will fail. We don't want this either.

Hopefully this illustrates better why I'm pursuing an embed of the tool rather than an out-of-band integration (like bsdoc currently has).

leostera avatar Feb 14 '19 09:02 leostera

Firstly, odoc needs to be compiled with a matching version of the compiler you are compiling your project with. This means the versioning of the npm package will have to include the version of the compiler as well.

Then your only real hope is to embed it into bs-platform as you are pursuing. Esy can generate prebuilt binaries for every platform including windows but it looks like bs-platform currently needs to compile on host for some platforms. If bs-platform ever goes full prebuilt binaries for everything, then you could use esy to pack up prebuilts of odoc, and then include those with bs-platform.

If bs-platform won't move to 100% prebuilt binaries, then you'd need to either improve bspack to understand dune, or fork bs-platform into an esy package that models a compiler dependency. Ultimately, at some point I think bs-platform is going to actually benefit from modelling a compiler dependency because then people can properly build ppx plugins (it could even be a prebuilt compiler version as long as it is modeled).

Alternatively, you could just have a separate prebuilt odoc npm package. I know it's tough to keep the compiler versions in sync since bs-platform doesn't model a dependency on the compiler, but still - odoc would be a devDependency and that simplifies a lot of things here.

jordwalke avatar Feb 14 '19 11:02 jordwalke

@ostera self contained means bs-platform could be built from source without extra deps. bs-platform is a compiler, technically it does not depend on the ocaml compiler(we have a vendored one, the user does not need to known about the internals).

For the version mismatch problem, the philosophy is quite different from ocaml native, I wish it would be mitigated to some extent given that we only have one major version maintained and maybe upgrade (changing cmt/cmti format) in every one and half an year.

Having odoc bspacked is the ideal solution, or we could spend major effort in shipping 4.06 for odoc

bobzhang avatar Feb 15 '19 07:02 bobzhang

@ostera I took a little time to digest your points :-) perhaps we can simplify some things. Suppose we go with a bs-platform-odoc separate package. We can version it to target specifically the version of BuckleScript it should work with. BuckleScript releases are not frequent enough that this should be a major pain. Plus, for each BuckleScript version, its OCaml version is fixed, and we know what it is (e.g. 4.02.3+BS now).

For example, current stable version of bs-platform is 4.0.18 (as of today); if we have a bs-platform-odoc targeting that version, we could give it exactly the same version number (4.0.18) and build it with exactly the same OCaml version (4.02.3+BS). And users don't need to install it separately. The bsb scaffolding feature can set up a project with it as a dev dependency with exactly the same version as bs-platform:

$ bsb -init myproj

Output package.json:

...
"scripts": {
  "docs": "odoc ..."
},
...
"devDependencies": {
  "bs-platform": "^4.0.18",
  "bs-platform-odoc": "^4.0.18"
}
...

After that, users would be just an npm install away from having full documentation generation. This seems like the best of both worlds.

yawaramin avatar Mar 17 '19 03:03 yawaramin

up, what is the state of it ? What is the current best way to manage documentation generation ? Kind of lost..

kiuKisas avatar Jul 16 '21 18:07 kiuKisas

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Aug 07 '23 05:08 stale[bot]