benjamn / recast

JavaScript syntax tree transformer, nondestructive pretty-printer, and automatic source map generator
MIT License
4.89k stars 344 forks source link

Extra parenthesis added to JSX elements containing comments even when AST is not modified #1386

Open haskellcamargo opened 4 months ago

haskellcamargo commented 4 months ago

Overview

Recast's documentation states the following:

The magic of Recast is that it reprints only those parts of the syntax tree that you modify. In other words, the following identity is guaranteed: recast.print(recast.parse(source)).code === source

However, it does not hold true in a specific scenario: when there are comments nested within JSX elements.

Behaviour

Consider the following code as input:

export const Table = () => {
   return (
    <List className={styles.topMargin}>
      <Rows>
        {alerts.map(alert => (
          // This is a comment
          <Alert id={alert} />
        ))}
      </Rows>
    </List>
  );
}

And the following configuration:

const ast = recast.parse(code, {
  parser: {
    parse: (source) =>
    parsers.babel.parse(source, {
      plugins: ["jsx"]
    })
  }
});

console.log(recast.print(ast).code);

One would expect the output to be the exact same as the input, as the AST is untouched. However, extra parenthesis are added to some of the JSX elements:

export const Table = () => {
    return (
-     <List className={styles.topMargin}>
+     (<List className={styles.topMargin}>
        <Rows>
          {alerts.map(alert => (
            // This is a comment
-           (<Alert id={alert} />)
+           (<Alert id={alert} />)
          ))}
        </Rows>
-     </List>)
+     </List>)
    );
 }

I wrote an AST Explorer example to reproduce the issue. Please note that the AST is not properly printed there due to the lack of proper support for customising parsers in the visualisation for Recast in AST Explorer, but the transformation applies properly, although it generates improper code.

tim-dev commented 2 weeks ago

I believe this is fixed in #1406