Preserve comments when downleveling arrow expression bodies - #4723
Conversation
There was a problem hiding this comment.
Pull request overview
Preserves leading comments when arrow expression bodies are downleveled into blocks, preventing ASI from skipping returned expressions.
Changes:
- Copies the expression source range to synthesized
returnstatements. - Adds compiler regression coverage and baselines.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
internal/printer/emitcontext.go |
Preserves the expression range on synthesized returns. |
testdata/tests/cases/compiler/optionalChainingArrowFunctionCommentEs2018.ts |
Adds the regression case. |
testdata/baselines/reference/compiler/optionalChainingArrowFunctionCommentEs2018.js |
Verifies correct comment placement in emitted JavaScript. |
testdata/baselines/reference/compiler/optionalChainingArrowFunctionCommentEs2018.types |
Records type output. |
testdata/baselines/reference/compiler/optionalChainingArrowFunctionCommentEs2018.symbols |
Records symbol output. |
|
also consider this test case from #4722 (comment) |
04f4c1f to
b0e85fb
Compare
Wesley Wigham (weswigham)
left a comment
There was a problem hiding this comment.
I still think it's a bit suspect that both the return statement and the containing block are getting the same text range set (at least without disabling some subset of comment emit on each) - to me, that seems like a recipe for getting some kinda function() /*comment*/ { /*comment*/ return expr; } duplicate output.
|
You're definitely right, but Strada double sets too: https://github.com/microsoft/TypeScript/blob/5848bc5157b22ff7f4e3369f4645a514a433b15f/src/compiler/factory/nodeConverters.ts#L54-L60 |
There was a problem hiding this comment.
You're right I suppose. Though I'm a little weirded out by the duplicate location-set in strada, too.
But! Another good point from that link brings up - there's already a convertToFunctionBlock in async.go (which actually has a triple identical .Loc set) that we should extract to a helper function and reuse in both places, so when we go back to fix that duplicate location down the line when it tracks back to the root cause of some weird comment emit issue, we have only one place to fix and not two.
|
Copilot Please address the above :) |
Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com>
Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com>
Addressed in aca5f3b and 70c3165.
Covered by the regression in de6d68f; the supplied single optional-chain case is included verbatim and its emitted comment placement is validated. |
…t/typescript-go#4723) Co-authored-by: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Fixes #4722
Analysis
Downleveling optional chains can introduce temporary variable declarations into an arrow function with an expression body.
VisitFunctionBodythen rewrites the expression body into a block containing those declarations and a synthesizedreturn.The synthesized
returnpreviously had no source range. Leading comments were therefore emitted with the returned expression, after thereturnkeyword:The newline triggers ASI, so the function returns
undefinedwithout evaluating the expression.Fix
Apply the original expression range to both the synthesized
returnand block, matching Strada'sconvertToFunctionBlock. Suppress comment emission on the rewritten expression so comments are owned by the enclosing synthesized statement instead of being emitted afterreturn.The compiler regression covers:
The first commit contains the test and known-bad baselines. The second contains the implementation and corrected JavaScript baseline. Inline comments retain Strada's existing duplicated emit behavior.
Copilot Checklist
I successfully ran these commands at the end of my session, and they completed without error: