@@ -113,59 +113,41 @@ namespace ts {
113113 }
114114 }
115115
116- function addConvertToAsyncFunctionDiagnostics ( node : FunctionLikeDeclaration , checker : TypeChecker , diags : DiagnosticWithLocation [ ] ) : void {
117-
118- if ( isAsyncFunction ( node ) || ! node . body ) {
119- return ;
116+ function addConvertToAsyncFunctionDiagnostics ( node : FunctionLikeDeclaration , checker : TypeChecker , diags : Push < DiagnosticWithLocation > ) : void {
117+ if ( ! isAsyncFunction ( node ) &&
118+ node . body &&
119+ isBlock ( node . body ) &&
120+ hasReturnStatementWithPromiseHandler ( node . body ) &&
121+ returnsPromise ( node , checker ) ) {
122+ diags . push ( createDiagnosticForNode (
123+ ! node . name && isVariableDeclaration ( node . parent ) && isIdentifier ( node . parent . name ) ? node . parent . name : node ,
124+ Diagnostics . This_may_be_converted_to_an_async_function ) ) ;
120125 }
126+ }
121127
128+ function returnsPromise ( node : FunctionLikeDeclaration , checker : TypeChecker ) : boolean {
122129 const functionType = checker . getTypeAtLocation ( node ) ;
123-
124130 const callSignatures = checker . getSignaturesOfType ( functionType , SignatureKind . Call ) ;
125131 const returnType = callSignatures . length ? checker . getReturnTypeOfSignature ( callSignatures [ 0 ] ) : undefined ;
126-
127- if ( ! returnType || ! checker . getPromisedTypeOfPromise ( returnType ) ) {
128- return ;
129- }
130-
131- // collect all the return statements
132- // check that a property access expression exists in there and that it is a handler
133- const returnStatements = getReturnStatementsWithPromiseHandlers ( node ) ;
134- if ( returnStatements . length > 0 ) {
135- diags . push ( createDiagnosticForNode ( ! node . name && isVariableDeclaration ( node . parent ) && isIdentifier ( node . parent . name ) ? node . parent . name : node , Diagnostics . This_may_be_converted_to_an_async_function ) ) ;
136- }
132+ return ! ! returnType && ! ! checker . getPromisedTypeOfPromise ( returnType ) ;
137133 }
138134
139135 function getErrorNodeFromCommonJsIndicator ( commonJsModuleIndicator : Node ) : Node {
140136 return isBinaryExpression ( commonJsModuleIndicator ) ? commonJsModuleIndicator . left : commonJsModuleIndicator ;
141137 }
142138
143- /** @internal */
144- export function getReturnStatementsWithPromiseHandlers ( node : Node ) : ReturnStatement [ ] {
145- const returnStatements : ReturnStatement [ ] = [ ] ;
146- if ( isFunctionLike ( node ) ) {
147- forEachChild ( node , visit ) ;
148- }
149- else {
150- visit ( node ) ;
151- }
152-
153- function visit ( child : Node ) {
154- if ( isFunctionLike ( child ) ) {
155- return ;
156- }
157-
158- if ( isReturnStatement ( child ) && child . expression && isFixablePromiseHandler ( child . expression ) ) {
159- returnStatements . push ( child ) ;
160- }
139+ function hasReturnStatementWithPromiseHandler ( body : Block ) : boolean {
140+ return ! ! forEachReturnStatement ( body , isReturnStatementWithFixablePromiseHandler ) ;
141+ }
161142
162- forEachChild ( child , visit ) ;
163- }
164- return returnStatements ;
143+ /* @internal */
144+ export function isReturnStatementWithFixablePromiseHandler ( node : Node ) : node is ReturnStatement {
145+ return isReturnStatement ( node ) && ! ! node . expression && isFixablePromiseHandler ( node . expression ) ;
165146 }
166147
167148 // Should be kept up to date with transformExpression in convertToAsyncFunction.ts
168- function isFixablePromiseHandler ( node : Node ) : boolean {
149+ /* @internal */
150+ export function isFixablePromiseHandler ( node : Node ) : boolean {
169151 // ensure outermost call exists and is a promise handler
170152 if ( ! isPromiseHandler ( node ) || ! node . arguments . every ( isFixablePromiseArgument ) ) {
171153 return false ;
0 commit comments