-
Notifications
You must be signed in to change notification settings - Fork 656
feature(formatter): format ASTs with missing tokens or nodes #1707
Conversation
if let Some(token) = self.function_token() { | ||
tokens.push(formatter.format_token(&token)); | ||
} | ||
tokens.push(formatter.format_token(&self.function_token()?)?); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to bail out (return None
) for tokens and children that are expected to be present in a valid sub-tree.
That means for mandatory fields (nodes and tokens) use formatter.format_token(&self.function_token()?)?);
and only use
if let Some(token) = self.star_token() {
tokens.push(formatter.format_token(&token)?)
}
for optional fields.
0120dd4
to
2970610
Compare
Deploying with
|
Latest commit: |
57aa2fb
|
Status: | ✅ Deploy successful! |
Preview URL: | https://a01b9632.tools-8rn.pages.dev |
2970610
to
2346445
Compare
]) | ||
fn to_format_element(&self, formatter: &Formatter) -> Option<FormatElement> { | ||
Some(group_elements(format_elements![ | ||
formatter.format_token(&self.l_paren_token()?)?, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will become formatter.format_token(&self.l_paren_token())?
if we implement my suggestion that mandatory tokens and nodes should be inserted by the parser (and thus, we can change the field accessors for mandatory fields to non-optional types).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me!
crates/formatter/src/formatter.rs
Outdated
/// Creates a [FormatElement] for the passed in node that will represent the node exactly as it | ||
/// is currently formatted in the source text (it actually doesn't change the formatting at all). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find this comment hard to read, can it be reworded?
Summary
Adds support for formatting ASTs with missing tokens or nodes which is the first step on our journey to support (partially) formatting source files with arbitrary syntax errors.
The main change is to return an
Option<FormatElement>
instead of aFormatElement
fromToFormatElement.to_format_element
if a node or token contains invalid content (e.g. a mandatory token or child node is missing). The parent has then the option to implement some recovery logic, for example inserting the node with its current formatting, or can propagate the formatting error (which most nodes will do).This PR does not address the issue where tokens and/or nodes are present in places they aren't expected in a valid syntax tree. For example, the formatter messes up the following file
becomes
because
script.items()
only returnsStmt
s but therslint
parser doesn't generate aStmt
for----
. Supporting these cases will require significant changes to the rslint parser, which is why we address this issue separately. See my update comment on #1700 for a more extensive explanation of the problem and what my plans are.Test Plan
Added a few spec tests but we should extend the test cases in the future.