-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
Support js codemods: represent whitespace decisions in AST #12709
Comments
Let's think about what's in involved in building this. The first obstacle is that prettier supports a number of parsers. They all represent what location data they do store a bit differently. Some have a We could store break and blank positions in sorted arrays at the root of the AST. It would be possible to quickly binary search the arrays to determine if any two nodes have a break or blank that falls between the end of one and the start of the next. This strategy would be fully resilient to the transforms removing nodes, e.g. { foo, bar }
// becoming
{ bar } or foo;
bar;
baz;
// becoming
foo;
baz; While that solves the problem of how to preserve the spacing coming from the original code, it doesn't help us with being able to make new whitespace in code that we generate, which by definition will not yet have any location information. For imports, object properties, or object patterns the entry list it makes sense I think to allow the owner node to be marked with a Statements are a bit harder. Let's say you're writing a transform to insert a thunk(() => {
first;
last;
});
thunk(() => {
first;
last;
}); You need to provide an API that can fully specify where a break does or does not belong. I propose this api: Combining these strategies allows us to create a more robust and powerful system for preserving whitespace and allowing it to be manipulated than either strategy alone would be able to offer, and could completely replace the existing dependence on having a source string present. When printing an AST with no location data at all the most compact form would be chosen except for places where prettier's rules demand blank lines. |
The way I've written the proposal usage of the |
I did a quick search through the code for Methods:
Other usages:prettier/src/language-js/print/comment.js Lines 16 to 21 in e23b89b
prettier/src/language-js/print/comment.js Lines 41 to 42 in e23b89b
prettier/src/language-js/print/flow.js Lines 306 to 311 in e23b89b
prettier/src/language-js/print/function.js Line 231 in e23b89b
prettier/src/language-js/print/module.js Lines 262 to 264 in e23b89b
|
Of all those the award for scaring me most goes to Those methods are used at times to peek for specific characters ( |
Prettier's printer basically has the shape |
I think the thing to do is to fork prettier and start ripping things out until I have a toy pretty-printer that's significantly easier to experiment on. Then I can actually try some of these techniques and understand better what it is I really want to propose and what the benefits and drawbacks are. |
Note to self: prettier's core data structure is |
I think I mentioned it on the recast thread, but the effective initial commit of this repo is quite interesting and informative. It has docs about internals that are no longer published anywhere, and it still is based closely enough on recast that it supports pretty-printing nodes which were programmatically inserted into the DOM. |
Next in the wayback machine, the introduction of Lines 2068 to 2090 in bcd44b4
Note that this is maybe 30 commits in, so there is very little history of this repository in which it has not been dependent on |
Other discussion of this issue: estree/estree#265 (comment) |
Which leads here: estree/estree#41 |
A practical-sounding proposal: estree/estree#41 (comment) |
OK as far as I can tell much of the existing discussion has been rolled up into cst, which appears to be much better than anything that I could propose. |
I'm going to close this issue and make a new one. I've said too much stuff that is just completely wrong or nonsensical, so I'm going to start over. |
Codemods are usually a process of reading a source into an AST, mutating the AST, then overwriting the original source with the modified version. To do this well you obviously need to preserve formatting to the greatest extent possible.
I'm going to start this is a meta-issue for several related issues I've found: #2068, #4675, #5998, and probably more that have some bearing on how to use prettier on a javascript AST. Currently prettier assumes when printing that the AST it has is unmodified. In particular it assumes that it can use the locations attached to nodes to inspect the original source text and determine whether there was whitespace in very specific cases where it preserves original formatting. Those cases are:
key: value
mappings inside brackets ({}
) on one or more linesEliminating the dependency on the source text would mean building this bit of state into the AST itself. I am strongly in favor of this, as building it into the AST should ensure that it is possible not just to preserve existing formatting, but to specify what formatting state can be specified programatically, for example by demanding that an inserted statement be padded with blank lines.
I think there's strong incentive to build this (and I would like to), as it would allow me to avoid using
recast
, which is currently a hassle as I have to use recast to transform a source, then print it, then use prettier to reformat the string.The text was updated successfully, but these errors were encountered: