Preserve comments when downleveling arrow expression bodies - #4723
Preserve comments when downleveling arrow expression bodies#4723Jake Bailey (jakebailey) with Copilot wants to merge 7 commits into
Conversation
Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com>
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. |
| if !ast.IsBlock(updated) { | ||
| statements := c.MergeEnvironment([]*ast.Statement{c.Factory.NewReturnStatement(updated)}, declarations) | ||
| returnStatement := c.Factory.NewReturnStatement(updated) | ||
| returnStatement.Loc = updated.Loc |
There was a problem hiding this comment.
This clones the expression's pos to the return statement - which is fine IF you also suppress comments on updated. As it is now, there may be duplicated comments in some situations (inline comments, likely).
There was a problem hiding this comment.
Copilot think harder, ground yourself in Strada's code, etc etc
There was a problem hiding this comment.
Addressed in 38e7d06. I now suppress comments on the rewritten expression when synthesizing the return in VisitFunctionBody, so we keep the ASI-safe return positioning without re-emitting comments from updated.
There was a problem hiding this comment.
Copilot did you actually have a test for this that showed the difference?
definitely consider redoing the stack such that the first commit is all tests, the second commit is all fixes indicating that things changed
Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com>
|
also consider this test case from #4722 (comment) |
Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com>
Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com>
| if sourceFile != nil { | ||
| tokenPos := scanner.GetTokenPosOfNode(parseNode, sourceFile, false /*includeJSDoc*/) | ||
| if tokenPos > parseNode.Pos() && | ||
| scanner.GetECMALineOfPosition(sourceFile, parseNode.Pos()) == scanner.GetECMALineOfPosition(sourceFile, tokenPos) { | ||
| c.AddEmitFlags(returnStatement, EFNoLeadingComments) | ||
| } | ||
| } |
There was a problem hiding this comment.
Copilot this is some interesting code; what did Strada do?
There was a problem hiding this comment.
Strada's convertToFunctionBlock simply applies the expression's text range to both the synthesized return and block (factory/nodeConverters.ts:54-60). It has no scanner check or comment suppression. That currently duplicates same-line comments, while suppressing return comments unconditionally loses preceding-line comments in tsgo; this conditional preserves the preceding-line case while avoiding the inline duplicate.
There was a problem hiding this comment.
Copilot Is there precedence for this in the repo? Existing helpers? Existing cases in the old compiler, even?
Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com>
Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com>
Downlevel optional chaining can hoist temporaries from an arrow expression body, forcing the body to become a block with a synthesized
return. When the expression had a leading comment, that comment emitted afterreturn, triggering ASI and skipping the expression.Emit fix
returnstatement.returninstead of betweenreturnand the returned expression.Regression coverage
Now emits with the comment before
return, avoidingreturn\n...ASI behavior.