@@ -82,7 +82,7 @@ const metadata = {
8282
8383 if ( ts . isFunctionDeclaration ( node ) ) {
8484 if ( node . name ?. getText ( ) === 'generateMetadata' ) {
85- if ( hasCorrectType ( node ) ) {
85+ if ( hasType ( node ) ) {
8686 return [ ]
8787 }
8888
@@ -103,7 +103,7 @@ const metadata = {
103103 }
104104 } else {
105105 for ( const declaration of node . declarationList . declarations ) {
106- if ( hasCorrectType ( declaration ) ) {
106+ if ( hasType ( declaration ) ) {
107107 return [ ]
108108 }
109109
@@ -209,7 +209,7 @@ const metadata = {
209209 if (
210210 declaration &&
211211 ts . isFunctionDeclaration ( declaration ) &&
212- ! hasCorrectType ( declaration )
212+ ! hasType ( declaration )
213213 ) {
214214 diagnostics . push ( {
215215 file : source ,
@@ -226,7 +226,7 @@ const metadata = {
226226 if (
227227 declaration &&
228228 ts . isVariableDeclaration ( declaration ) &&
229- ! hasCorrectType ( declaration )
229+ ! hasType ( declaration )
230230 ) {
231231 diagnostics . push ( {
232232 file : source ,
@@ -246,144 +246,40 @@ const metadata = {
246246 } ,
247247}
248248
249- function hasCorrectType (
250- node : tsModule . FunctionDeclaration | tsModule . VariableDeclaration
251- ) : boolean {
252- // Skip if already has type.
253- if ( node . type ) {
254- return true
255- }
256-
257- const ts = getTs ( )
258- const typeChecker = getTypeChecker ( )
259- if ( ! typeChecker ) {
260- return false
261- }
262-
263- // For generateMetadata, check if it's Promise<Metadata> for async or Metadata for sync
264- if ( ts . isFunctionDeclaration ( node ) ) {
265- return checkFunctionReturnType ( node , typeChecker )
266- } else {
267- // For variable declarations (const/let/var)
268- const name = node . name . getText ( )
269-
270- if ( name === 'generateMetadata' ) {
271- // For generateMetadata as a variable, it must be a function expression or arrow function
272- if (
273- ! node . initializer ||
274- ( ! ts . isFunctionExpression ( node . initializer ) &&
275- ! ts . isArrowFunction ( node . initializer ) )
276- ) {
277- return false
278- }
279-
280- // Check the return type of the function expression/arrow function
281- if ( node . initializer . type ) {
282- // If it has an explicit return type annotation
283- return checkFunctionReturnType ( node . initializer , typeChecker )
284- } else {
285- // If no explicit return type, infer it from the function
286- const signature = typeChecker . getSignatureFromDeclaration (
287- node . initializer
288- )
289- if ( ! signature ) return false
290-
291- const returnType = typeChecker . getReturnTypeOfSignature ( signature )
292- if ( ! returnType ) return false
293-
294- const isAsync =
295- node . initializer . modifiers ?. some (
296- ( m ) => m . kind === ts . SyntaxKind . AsyncKeyword
297- ) ?? false
298-
299- if ( isAsync ) {
300- // For async functions, check if it's Promise<Metadata>
301- const typeSymbol = returnType . getSymbol ( )
302- if ( ! typeSymbol || typeSymbol . getName ( ) !== 'Promise' ) return false
303-
304- // Check if it's a reference type (like Promise<T>)
305- if (
306- ! ( returnType . flags & ts . TypeFlags . Object ) ||
307- ! ( 'typeArguments' in returnType )
308- ) {
309- return false
310- }
311-
312- const typeArgs = (
313- returnType as { typeArguments : readonly tsModule . Type [ ] }
314- ) . typeArguments
315- if ( ! typeArgs || typeArgs . length !== 1 ) return false
316-
317- const promiseType = typeArgs [ 0 ]
318- const promiseTypeSymbol = promiseType . getSymbol ( )
319- return promiseTypeSymbol ?. getName ( ) === 'Metadata'
320- } else {
321- // For sync functions, check if it returns Metadata
322- const returnTypeSymbol = returnType . getSymbol ( )
323- return returnTypeSymbol ?. getName ( ) === 'Metadata'
324- }
325- }
326- } else {
327- // For metadata export, we just need Metadata type
328- if ( ! node . type ) return false
329- const type = typeChecker . getTypeFromTypeNode ( node . type )
330- if ( ! type ) return false
331- const symbol = type . getSymbol ( )
332- return symbol ?. getName ( ) === 'Metadata'
333- }
334- }
335- }
336-
337- function checkFunctionReturnType (
249+ function hasType (
338250 node :
339251 | tsModule . FunctionDeclaration
252+ | tsModule . VariableDeclaration
340253 | tsModule . FunctionExpression
341- | tsModule . ArrowFunction ,
342- typeChecker : tsModule . TypeChecker
254+ | tsModule . ArrowFunction
343255) : boolean {
344256 const ts = getTs ( )
345257
346- if ( ! node . type ) return false
347-
348- const returnType = typeChecker . getTypeFromTypeNode ( node . type )
349- if ( ! returnType ) return false
350-
351- const isAsync =
352- node . modifiers ?. some ( ( m ) => m . kind === ts . SyntaxKind . AsyncKeyword ) ?? false
353-
354- if ( isAsync ) {
355- // For async functions, we need Promise<Metadata>
356- const typeSymbol = returnType . getSymbol ( )
357- if ( ! typeSymbol || typeSymbol . getName ( ) !== 'Promise' ) {
358- return false
359- }
360-
361- // Get the type argument of Promise<T>
362- if ( ! ts . isTypeReferenceNode ( node . type ) ) {
363- return false
364- }
258+ // For function declarations, expressions, and arrow functions, check if they have return type
259+ if (
260+ ts . isFunctionDeclaration ( node ) ||
261+ ts . isFunctionExpression ( node ) ||
262+ ts . isArrowFunction ( node )
263+ ) {
264+ return ! ! node . type
265+ }
365266
366- // Check if it's a reference type (like Promise<T>)
267+ // For variable declarations
268+ if ( ! node . name ) return false
269+ const name = node . name . getText ( )
270+ if ( name === 'generateMetadata' ) {
271+ // If it's a function expression or arrow function, check if it has return type
367272 if (
368- ! ( returnType . flags & ts . TypeFlags . Object ) ||
369- ! ( 'typeArguments' in returnType )
273+ node . initializer &&
274+ ( ts . isFunctionExpression ( node . initializer ) ||
275+ ts . isArrowFunction ( node . initializer ) )
370276 ) {
371- return false
372- }
373-
374- const typeArgs = ( returnType as { typeArguments : readonly tsModule . Type [ ] } )
375- . typeArguments
376- if ( ! typeArgs || typeArgs . length !== 1 ) {
377- return false
277+ return ! ! node . initializer . type
378278 }
379- const promiseType = typeArgs [ 0 ]
380- const promiseTypeSymbol = promiseType . getSymbol ( )
381- return promiseTypeSymbol ?. getName ( ) === 'Metadata'
382- } else {
383- // For sync functions, we need Metadata directly
384- const symbol = returnType . getSymbol ( )
385- return symbol ?. getName ( ) === 'Metadata'
386279 }
280+
281+ // For all other cases, check if the node has a type annotation
282+ return ! ! node . type
387283}
388284
389285export default metadata
0 commit comments