Skip to content

JSX formatting does not de-indent closing tag with text body #20766

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

Closed
mjbvz opened this issue Dec 18, 2017 · 5 comments · Fixed by #36552
Closed

JSX formatting does not de-indent closing tag with text body #20766

mjbvz opened this issue Dec 18, 2017 · 5 comments · Fixed by #36552
Assignees
Labels
Bug A bug in TypeScript Domain: Formatter The issue relates to the built-in formatter Fix Available A PR has been opened for this issue VS Code Priority Critical issues that VS Code needs fixed in the current TypeScript milestone

Comments

@mjbvz
Copy link
Contributor

mjbvz commented Dec 18, 2017

From microsoft/vscode#40454 (comment)

TypeScript Version: 2.7.0-dev.20171214

Code

(
    <div>
        text
        </div>
)

Run format

Expected behavior:

(
    <div>
        text
    </div>
)

Actual behavior:
No change. Content remains:

(
    <div>
        text
        </div>
)

The </div> is de-indented if the body is a tag instead of text:

(
    <div>
        <span />
        </div>
)
@mjbvz mjbvz added the VS Code Tracked There is a VS Code equivalent to this issue label Dec 18, 2017
@mhegazy mhegazy added Bug A bug in TypeScript Domain: Formatter The issue relates to the built-in formatter Help Wanted You can do this labels Jan 4, 2018
@mhegazy mhegazy added this to the Community milestone Jan 4, 2018
@srolel
Copy link
Contributor

srolel commented Jan 10, 2018

@mhegazy I've been working on this, and it looks like this doesn't get formatted because the linebreak and whitespace between text and </div> are consumed by the scanner as a part of the SyntaxKind.JsxText token. I have a fix I can submit but I want to make sure this would be the right behavior (removing the whitespace). This does agree with JSX compilation, where the compiled string does not include any leading/trailing whitespace, so this would not have any effect on compiled code, as it should.

The fix is along the lines of stopping after the linebreak, which will make the closing </div> tag have that whitespace as leadingTrivia which will get formatted correctly.

@mhegazy
Copy link
Contributor

mhegazy commented Jan 10, 2018

sounds reasonable. I have not looked at the formatting scanner in a while, so i will need to look at the change, and look around to see if i can poke holes into the fix.

@orta
Copy link
Contributor

orta commented Jan 24, 2020

It's getting late on a Friday, so I'm leaving myself some notes:

Today the text nodes inside the JSXText are this range:

 <div>
     |text
   |</div>

Which includes the trailing whitespace. To fix this bug I've explored (a):

<div>
  |text|
    </div>

and (b)

<div>
  |text
|   </div>

b is is what Mosho1 recommends above, and a seems promising but needs some finessing somewhere also.

Issues:

  • It's changing some of the JS emit unpredictably:

    • React.createElement(Bar, null, " q "),
      -> React.createElement(Bar, null, " q"," "),
  • It's bringing up new formatting issues:

    • This code isn't indenting the 'goodbye' on the 2nd line
      function foo() {
      return (
              <div>
      hello
      goodbye
              </div>
          )
      }
      

There's a good chance the first one is a fencepost error somewhere, but the second I've not figured out yet. WIP here

@orta
Copy link
Contributor

orta commented Jan 29, 2020

After amending the parser, it looks like the next issues is that we don't handle JSX siblings affecting indentation: All of these spans are siblings to the divs in the AST:

(
    <div>
        <span/>
        <span/>
        <div id="x">
            <p>OK</p>
        </div>
        <span/>
        <span/>
    </div>
)

Which on master today formats to:

(
    <div>
    <span/>
    < span />
    <div id= "x" >
    <p>OK < /p>
    < /div>
    < span />
    <span/>
    < /div>
)

Which is kinda wild because that code isn't legit JSX.

@orta
Copy link
Contributor

orta commented Jan 29, 2020

It wasn't legit JSX, because it wasn't declared to be a JSX file - doh.

@orta orta added Fix Available A PR has been opened for this issue and removed Help Wanted You can do this labels Feb 3, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Domain: Formatter The issue relates to the built-in formatter Fix Available A PR has been opened for this issue VS Code Priority Critical issues that VS Code needs fixed in the current TypeScript milestone
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants