@@ -101,35 +101,32 @@ function touchCommandOf(switchCase: AstNode): (typeof TOUCH_DISPATCH_COMMANDS)[n
101101 : null ;
102102}
103103
104+ /** The callee of a case body that is exactly one `return await <callee>(...)`, else undefined. */
105+ function awaitedCallee ( switchCase : AstNode ) : AstNode | undefined {
106+ const [ statement , ...rest ] = switchCase . consequent as AstNode [ ] ;
107+ if ( rest . length > 0 || statement ?. type !== 'ReturnStatement' ) return undefined ;
108+ const awaited = statement . argument ;
109+ if ( ! isAstNode ( awaited ) || awaited . type !== 'AwaitExpression' ) return undefined ;
110+ const call = awaited . argument ;
111+ return isAstNode ( call ) && call . type === 'CallExpression' ? ( call . callee as AstNode ) : undefined ;
112+ }
113+
104114/** The touch handler a case delegates to, or why it is not a pure delegation. */
105115function delegationOf (
106116 switchCase : AstNode ,
107117 handlers : ReadonlySet < string > ,
108118) : { handler : string } | { violation : string } {
109- const consequent = switchCase . consequent as AstNode [ ] ;
110- if ( consequent . length !== 1 || consequent [ 0 ] ?. type !== 'ReturnStatement' ) {
111- return { violation : 'the case body is not exactly one return statement' } ;
112- }
113- const awaited = consequent [ 0 ] . argument ;
114- if ( ! isAstNode ( awaited ) || awaited . type !== 'AwaitExpression' ) {
115- return { violation : 'the case does not return an awaited call' } ;
116- }
117- const call = awaited . argument ;
118- if ( ! isAstNode ( call ) || call . type !== 'CallExpression' ) {
119- return { violation : 'the case does not return an awaited call' } ;
119+ const callee = awaitedCallee ( switchCase ) ;
120+ if ( callee === undefined ) {
121+ return { violation : 'the case body is not exactly one `return await <handler>(...)`' } ;
120122 }
121- const callee = call . callee ;
122- if ( ! isAstNode ( callee ) || callee . type !== 'Identifier' ) {
123- return {
124- violation : 'the case calls something other than an imported touch handler' ,
125- } ;
123+ if ( callee . type !== 'Identifier' ) {
124+ return { violation : 'the case calls something other than an imported touch handler' } ;
126125 }
127126 const handler = String ( callee . name ) ;
128127 return handlers . has ( handler )
129128 ? { handler }
130- : {
131- violation : `\`${ handler } \` is not imported from an interaction-touch*.ts handler` ,
132- } ;
129+ : { violation : `\`${ handler } \` is not imported from an interaction-touch*.ts handler` } ;
133130}
134131
135132/**
@@ -268,7 +265,7 @@ test('the dispatcher guard rejects a hand-rolled responseData hidden behind a ne
268265 ) ,
269266 ) ;
270267 assert . deepEqual ( touchDispatchViolations ( source ) , [
271- "case 'press': the case body is not exactly one return statement " ,
268+ "case 'press': the case body is not exactly one ` return await <handler>(...)` " ,
272269 ] ) ;
273270} ) ;
274271
@@ -280,7 +277,7 @@ test('the dispatcher guard rejects a touch case that returns something other tha
280277 ) ,
281278 ) ;
282279 assert . deepEqual ( touchDispatchViolations ( inline ) , [
283- "case 'fill': the case does not return an awaited call " ,
280+ "case 'fill': the case body is not exactly one `return await <handler>(...)` " ,
284281 ] ) ;
285282
286283 const foreign = dispatcher (
0 commit comments