Rescript-compiler: Pass the output through a formatter

Created on 20 Aug 2016  路  8Comments  路  Source: rescript-lang/rescript-compiler

Like esformat? This way we don't have to worry about indentations for e.g. callbacks (unless that was indented?).

  return foo({
              bar: baz,
            });

cc @harrisonw

COMMUNITY enhancement

Most helpful comment

People seem to be excited about bucklescript because it outputs very idiomatic JavaScript. Since one of the main selling point is to actually look at the transformed output, I think it's important to spend time working on making the indentation feel like it would have been written by a JavaScript developer as it should be relatively straightforward (to get 95% there) and have a big impact on perception.

Context: https://twitter.com/Vjeux/status/775146356813901824

All 8 comments

@chenglou good idea, do you think we can provide some options in bsc so that it is easier to build a third party tool?

Btw I'd like bsc to avoid becoming a module bundler & build system a-la web pack. JS already has webpack. Adding configs for bsc output might be a slippery slope.

However, the reason why I think pretty printing JS is fine to introduce is because nobody use a JS pretty-printer as a build step in js land. It's handwritten code so nobody expects it to be altered for prettiness (it might be passed through a transpiler, whose output you wouldn't read/is well indented anyway).

It makes sense for BS because currently the compiler's output of indentation and spacing aren't that "idiomatic" to handwritten code. This can either be fixed inside the compiler, or you can lazy out by making an existing prettifier do it.

Tldr I'm suggesting a prettifier for BSC's convenience only, not as a pluggable build step built into the compiler (because nobody uses it).

People seem to be excited about bucklescript because it outputs very idiomatic JavaScript. Since one of the main selling point is to actually look at the transformed output, I think it's important to spend time working on making the indentation feel like it would have been written by a JavaScript developer as it should be relatively straightforward (to get 95% there) and have a big impact on perception.

Context: https://twitter.com/Vjeux/status/775146356813901824

There's a balance to be struck here. On one hand, a robust code formatter can produce very idiomatic indentation. On the other hand, it's potentially very slow in doing so. I'd suggest simply extending the pretty printer that you've already got in js_dump; adding a few more primitives to control nesting and vertical alignment.

I've had extremely good success with this O(n) time and O(1) space algorithm: lazy v. yield incremental linear pretty-printing. An implementation of this algorithm along with a simple Clojure pretty printer can be found in fipp.

@brandonbloom agreed, making the pretty printer a bit smarter to output not crazy looking code seems like a much better solution that piping another tool that's going to parse and pretty-print the code.

Hi all, thanks for your suggestions, it would certainly be much better to have a nice formatter.
Previously we use OCaml's stdlib Format, but there are some subtle issues, since Javascript is a
white- space sensitive language (ASI, etc).
To make the output more _solid_(better to work than pretty buggy code), I rolled a naive pretty printer so that we can have precise control when a new line will be inserted.
I am happy to continue improving the output (I don't think that will affect the compilation performance) or accept contributions, but I have to admit that it is not the top priority at the time.

If anyone needs some inspiration on writing pretty-printers, here's one I wrote not so long ago for a subset of JS:

https://github.com/Virum/compiler/blob/master/JavaScript.ml

Test suite:

https://github.com/Virum/compiler/blob/master/JavaScriptTest.ml

I tried to compare it to BuckleScript's output. In some places it's better, in some鈥攚orse.

/* BuckleScript */
return append(sort(List.filter(function (u) {
                      return Caml_obj.caml_lessequal(u, x);
                    })(xs)), /* :: */[
            x,
            sort(List.filter(function (u) {
                        return Caml_obj.caml_greaterthan(u, x);
                      })(xs))
          ]);

/* Virum */
return append(sort(List.filter(function (u) {
                               return Caml_obj.caml_lessequal(u, x);
                             })(xs)),
              [
                x,
                sort(List.filter(function (u) {
                                 return Caml_obj.caml_greaterthan(u, x);
                               })(xs))
              ]);"

I haven't hit any limitations of the Format module, but I only covered a modest subset of JS.

+1 for having the option to pipe the BuckleScript output through a formatter of choice.

This seems to be the lowest-friction solution for those who want to gradually adopt BuckleScript-compiled code (e.g. ReasonML):

  1. JS formatting will be consistent with the rest of the codebase (same Prettier/ESLint config). Due to the wide range of ESLint options, the output can diverge quite a bit.
  2. Using the same formatter will not conflict with pre-commit hooks that run modified files through Prettier.
  3. Opening and saving .bs.js files will not modify unchanged files for editors with format-on-save enabled
Was this page helpful?
0 / 5 - 0 ratings

Related issues

bobzhang picture bobzhang  路  3Comments

paparga picture paparga  路  5Comments

TheSpyder picture TheSpyder  路  5Comments

bobzhang picture bobzhang  路  3Comments

bobzhang picture bobzhang  路  4Comments