-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
convertToEs6Module: Avoid replacing entire function #22507
Conversation
3fde583
to
9e99f5d
Compare
9e99f5d
to
5c13eaf
Compare
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.
Minor concerns.
////} | ||
|
||
// TODO: GH#22492 Should be a able access `exports.z` inside `exports.f` | ||
|
||
verify.codeFix({ | ||
description: "Convert to ES6 module", | ||
// TODO: GH#22492 |
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.
Isn't this the bug that this change fixes?
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.
👍
if (lparen) { | ||
// `() => {}` --> `function f() {}` | ||
this.insertNodesAt(sourceFile, lparen.getStart(sourceFile), [createToken(SyntaxKind.FunctionKeyword), createIdentifier(name)], { joiner: " " }); | ||
this.deleteNode(sourceFile, arrow); |
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.
Will this destroy any trivia? Does it matter?
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.
This is a bug already, see #23373
const arrow = findChildOfKind(node, SyntaxKind.EqualsGreaterThanToken, sourceFile)!; | ||
const lparen = findChildOfKind(node, SyntaxKind.OpenParenToken, sourceFile); | ||
if (lparen) { | ||
// `() => {}` --> `function f() {}` |
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.
Does this work for () => true
?
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.
(Or is there some reason that's impossible here?)
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.
See if (node.body.kind !== SyntaxKind.Block)
below
src/services/textChanges.ts
Outdated
} | ||
else { | ||
// `x => {}` -> `function f(x) {}` | ||
this.insertNodesAt(sourceFile, first(node.parameters).getStart(sourceFile), [createToken(SyntaxKind.FunctionKeyword), createIdentifier(name + "(")], { joiner: " " }); |
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.
The lparen is in the identifier because we don't want a space between them? If we're going to do that, why not just insert raw text?
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.
Good idea, when I first wrote this we didn't have insertText
.
src/services/textChanges.ts
Outdated
else { | ||
// `x => {}` -> `function f(x) {}` | ||
this.insertNodesAt(sourceFile, first(node.parameters).getStart(sourceFile), [createToken(SyntaxKind.FunctionKeyword), createIdentifier(name + "(")], { joiner: " " }); | ||
// Replaceing full range of arrow to get rid of the leading space -- replace ` =>` with `)` |
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.
Typo "replaceing"
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.
👍
src/services/textChanges.ts
Outdated
// `x => {}` -> `function f(x) {}` | ||
this.insertNodesAt(sourceFile, first(node.parameters).getStart(sourceFile), [createToken(SyntaxKind.FunctionKeyword), createIdentifier(name + "(")], { joiner: " " }); | ||
// Replaceing full range of arrow to get rid of the leading space -- replace ` =>` with `)` | ||
this.replaceRange(sourceFile, arrow, createToken(SyntaxKind.CloseParenToken)); |
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.
This will definitely clobber trivia.
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.
@@ -303,7 +300,27 @@ namespace ts.codefix { | |||
return makeExportDeclaration([createExportSpecifier(/*propertyName*/ undefined, "default")], moduleSpecifier); | |||
} | |||
|
|||
function convertExportsDotXEquals(name: string | undefined, exported: Expression): Statement { | |||
function convertExportsDotXEquals({ left, right, parent }: BinaryExpression & { left: PropertyAccessExpression }, sourceFile: SourceFile, changes: textChanges.ChangeTracker): void { |
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.
Could "ExportsDotXEquals" be rephrased as "ExportsPropertyAssignment"?
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.
👍
const name = left.name.text; | ||
if ((isFunctionExpression(right) || isArrowFunction(right) || isClassExpression(right)) && (!right.name || right.name.text === name)) { | ||
// `exports.f = function() {}` -> `export function f() {}` -- Replace `exports.f = ` with `export `, and insert the name after `function`. | ||
changes.replaceRange(sourceFile, { pos: left.getStart(sourceFile), end: right.getStart(sourceFile) }, createToken(SyntaxKind.ExportKeyword), { suffix: " " }); |
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.
Will this clobber trivia on the LHS of the assignment?
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.
if (!right.name) changes.insertName(sourceFile, right, name); | ||
|
||
const semi = findChildOfKind(parent, SyntaxKind.SemicolonToken, sourceFile); | ||
if (semi) changes.deleteNode(sourceFile, semi, { useNonAdjustedEndPosition: true }); |
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.
Will this clobber trailing trivia on the semicolon?
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.
Fixes #22492
Will rebase once #22361 is in.