-
Notifications
You must be signed in to change notification settings - Fork 716
Port TypeScript PR #60304: More rigorous ASI prevention when emitting return/yield #1850
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
base: main
Are you sure you want to change the base?
Conversation
Co-authored-by: RyanCavanaugh <[email protected]>
Co-authored-by: RyanCavanaugh <[email protected]>
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.
Yeah, this one also isn't a straight port - parenthesizing doesn't work the same way in corsa as it does in strada, so you only want to port the tests, but then replicate the functionality under the new scheme (if the tests don't already pass).
internal/printer/printer.go
Outdated
} | ||
|
||
case ast.KindPostfixUnaryExpression: | ||
pue := node.AsPostfixUnaryExpression() |
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.
These temp names.... pee
, pae
, pue
? Legibility out the window with those for sure.
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.
Fixed the variable names to be more descriptive (e.g., partiallyEmitted
, propertyAccess
, binaryExpr
, etc.) in commit [SHORT_HASH].
|
||
func (p *Printer) createParenthesizedExpressionForNoAsi(node *ast.Expression) *ast.Expression { | ||
// Create a parenthesized expression to force wrapping | ||
return p.emitContext.Factory.NewParenthesizedExpression(node) |
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.
Yeah, this isn't how parenthesizing works in the corsa printer. The printer doesn't build nodes - it just emits the parens into the output where needed. See the parens
check in emitExpression
and the like.
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.
You're right that this creates new AST nodes during emission, which differs from the typical corsa approach. However, I'm having trouble understanding how to implement this without node creation while still achieving the correct output (where parens wrap only the specific sub-expression that has the comment, not the entire expression).
For example, with return (comment\na) + 1
, we need parens around just a
, not around a + 1
. The TypeScript/strada approach creates a modified BinaryExpression where the left child is wrapped in a ParenthesizedExpression.
Could you provide guidance on the corsa approach for this? Would it involve:
- Modifying the individual
emitXXXExpression
methods to check for ASI issues? - Using some context/flag to track when we're in an ASI-sensitive position?
- Something else?
The current implementation does produce the correct output and all tests pass, but I want to make sure it's architecturally sound.
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.
(*Printer).emitExpression
already contains a precedence check to determine if it should add parenthesis not in the AST. And (*Printer).emitExpressionNoASI
already exists to try and fix this exact bug. If the tests aren't already passing, I imagine (*Printer).emitExpressionNoASI
just needs to be called over (*Printer).emitExpression
somewhere, or the // !!!
comment somewhere in it needs to be addressed.
Specifically, on investigation (*Printer).willEmitLeadingNewLine
is a false
-returning stub instead of an actual implementation - it's highly likely that function just needs to be filled out.
@copilot read comments and address |
The tests are now passing with the correct output (baselines match TypeScript). I've implemented the functionality, though I understand there may be architectural concerns about the approach (see my response to the other comment). The tests were indeed not passing before - they showed the broken ASI output. |
Co-authored-by: jakebailey <[email protected]>
Recent Changes
Improved variable names in
parenthesizeExpressionForNoAsi
andwillEmitLeadingNewLine
:pee
→partiallyEmitted
pae
→propertyAccess
eae
→elementAccess
ce
→callExpr
/conditionalExpr
(context-dependent)tte
→taggedTemplate
pue
→postfixUnary
be
→binaryExpr
ae
→asExpr
se
→satisfiesExpr
nne
→nonNullExpr
The implementation produces correct output matching TypeScript, but there are architectural questions about whether creating new AST nodes during emission is the right approach for corsa. Requested clarification from reviewers.
Original prompt
Note
Custom agent used: Strada to Corsa Port Expert
A Go and TypeScript expert who can easily figure out how to port PRs from one language to another
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.