DanielXMoore / Civet

A TypeScript superset that favors more types and less typing
https://civet.dev
MIT License
1.54k stars 32 forks source link

Formatter #956

Open edemaine opened 8 months ago

edemaine commented 8 months ago

Civet should either gain a "formatter" mode, or its AST should become rich enough to support a separate formatter tool (probably in the same repo still, because AST changes need to be closely tied). Here are possible specific formatting rules we might aim for:

Detecting issues should be doable with the AST, possibly once it's fleshed out more. (Ideally we can do this piece by piece.) There are two possible ways to do the emit process:

  1. Keep track of the entire Civet source in the AST somehow, in particular no longer throwing away compiled-away tokens like then. We've discussed this for other purposes too (#40?). Maybe something parallel to token like source... The trouble with this is that it requires a lot of work before we can get anything working.
  2. Use source maps to translate all edits of surviving tokens back to modifications to the Civet code. So e.g. when converting f(x) to f x, we find the location of ( and replace it with `, and find the location of)` and remove it. These edits can be applied to the original source code all at once at the end, and then the file can be re-emitted. (Somewhat similar to LSP auto completions.) This is more annoying to work with, and will still require adding some Civet-only tokens that don't normally get emitted, but it's easier to get started with.

By contrast, I don't think Civet should gain a full "lint" mode that tests for bugs. See Prettier on formatting vs. code-quality rules. I think ideally the output of Civet would be compatible with most eslint code-quality rules, so we can use eslint directly for those. But formatting is fundamentally tied to the Civet source, not the generated JS/TS.

This post distills Discord discussion with @bbrk24.

bbrk24 commented 8 months ago

Preferred "no implicit return" style: :void vs. trailing comma.

Comma? Not semicolon?

A couple other rules I thought of:

gwhitney commented 8 months ago

Are you conceiving of the rule list posted here as a list of options that the user of the formatter can go either way on, or are you seeking a One True Civet Format in which the formatter would embody one specific choice on each option (i.e., be "opinionated" in the sense of Prettier)? I ask because in one project I worked on, we all hated one or two of Prettier's choices enough that we invested a fair amount of time in tooling that ran Prettier and then eslint -fix to undo what we saw as a couple bad choices by the creators of Prettier. That was a pain.

bbrk24 commented 8 months ago

Some of these would have to be configurable (maximum line length and :void vs ; for example). Ideally, it would be possible to turn all of these off individually, just like with ESLint.

edemaine commented 8 months ago

One True Civet Format

Definitely not that. There are so many ways to do things in Civet, and different people have different preferences on what they want to use. The goal is to make these choices fully configurable, to the extent possible (unlike Prettier). We will try to choose reasonable defaults, though. Of course, it's all speculation at the moment. :-)

danielbayley commented 8 months ago

Civet should either gain a "formatter" mode, or its AST should become rich enough to support a separate formatter tool

Preferably the latter, and with ESLint support (https://github.com/DanielXMoore/Civet/discussions/852) ideally work with eslint --fix.

See also ESLint Stylistic, and https://antfu.me/posts/why-not-prettier.

edemaine commented 8 months ago

I doubt we'd be able to make an AST that's eslint compatible, given how different Civet is from JS. This is the approach taken by CoffeeScript, and in my experience, it's rather fragile (only works on old eslint versions), so I'd hesitate to even try here.

For this reason, I think we need to do formatting ourselves from scratch. We're planning to make it highly configurable, taking best ideas from eslint and Prettier.

On the other hand, we'd like to use existing eslint rules for semantic checks, because that could hopefully be done just on the transformed JS. Hence why this issue is about formatting only. (Of course, it's a blurry line, so maybe one day our formatter does semantic checks too. But this is all hypothetical at the moment.)

bear-ei commented 4 months ago

Are there any new developments in this discussion. When I try to use Civet in some projects I migrate a lot of code from the original TS. The lack of a formatting tool makes this process extremely difficult. I spend a lot of time tweaking formatting errors to fit Civet.

edemaine commented 4 months ago

No, no progress yet. (If there were, it would be reported here.)

If you're converting from TS, you might consider running Prettier first, and/or check out ts2civet.