Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion src/services/codefixes/convertToAsyncFunction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
namespace ts.codefix {
const fixId = "convertToAsyncFunction";
const errorCodes = [Diagnostics.This_may_be_converted_to_an_async_function.code];
let codeActionSucceeded = true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

codeActionSucceeded [](start = 8, length = 19)

I assume this is the thing you were talking about when you asked about exceptions. It's not what I would have done, but it sounds like you've already checked the local conventions. I might change it to codeActionFailed though. As long as we're going down this path, would it make sense to have an error code indicating how it went wrong and then send a telemetry event when we see a failure?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure this is an appropriate place to bubble up an error code given the change to be more conservative about offering the diagnostic. That is, we won't show the diagnostic if we know the code fix is going to fail.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I think I was unclear. I didn't mean a diagnostic error code, I meant an enum or something that would tell you the reason the code action didn't succeed. And bubbling up would be to us, via telemetry, not to the user.

registerCodeFix({
errorCodes,
getCodeActions(context: CodeFixContext) {
codeActionSucceeded = true;
const changes = textChanges.ChangeTracker.with(context, (t) => convertToAsyncFunction(t, context.sourceFile, context.span.start, context.program.getTypeChecker(), context));
return [createCodeFixAction(fixId, changes, Diagnostics.Convert_to_async_function, fixId, Diagnostics.Convert_all_to_async_functions)];
return codeActionSucceeded ? [createCodeFixAction(fixId, changes, Diagnostics.Convert_to_async_function, fixId, Diagnostics.Convert_all_to_async_functions)] : [];
},
fixIds: [fixId],
getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, err) => convertToAsyncFunction(changes, err.file, err.start, context.program.getTypeChecker(), context)),
Expand Down Expand Up @@ -387,6 +389,9 @@ namespace ts.codefix {
const hasArgName = argName && argName.identifier.text.length > 0;
const shouldReturn = transformer.setOfExpressionsToReturn.get(getNodeId(parent).toString());
switch (func.kind) {
case SyntaxKind.NullKeyword:
// do not produce a transformed statement for a null or undefined argument
break;
case SyntaxKind.Identifier:
if (!hasArgName) break;

Expand Down Expand Up @@ -443,6 +448,9 @@ namespace ts.codefix {
return createNodeArray([createReturn(getSynthesizedDeepClone(funcBody) as Expression)]);
}
}
default:
// We've found a transformation body we don't know how to handle, so the refactoring should no-op to avoid deleting code.
codeActionSucceeded = false;
break;
}
return createNodeArray([]);
Expand Down
Loading