@@ -11,7 +11,7 @@ use biome_js_syntax::{
1111 AnyJsExpression , JsClassExpression , JsExport , JsFileSource , JsForStatement ,
1212 JsFunctionExpression , JsIdentifierExpression , JsImport , JsModule , JsModuleItemList ,
1313 JsSequenceExpression , JsSyntaxKind , JsSyntaxNode , TsConditionalType , TsDeclarationModule ,
14- TsInferType , TsInterfaceDeclaration , TsModuleDeclaration ,
14+ TsInferType ,
1515} ;
1616use biome_rowan:: { AstNode , BatchMutationExt , Direction , SyntaxResult } ;
1717use biome_rule_options:: no_unused_variables:: NoUnusedVariablesOptions ;
@@ -413,33 +413,35 @@ impl Rule for NoUnusedVariables {
413413/// Returns `true` if the file is considered a script
414414/// and is an interface or namespace
415415fn is_script_declaration ( binding : & AnyJsIdentifierBinding ) -> bool {
416+ // Verify this binding is from an interface or namespace
417+ let Some ( decl) = binding. declaration ( ) else {
418+ return false ;
419+ } ;
420+
421+ let is_interface_or_namespace = matches ! (
422+ decl,
423+ AnyJsBindingDeclaration :: TsInterfaceDeclaration ( _)
424+ | AnyJsBindingDeclaration :: TsModuleDeclaration ( _)
425+ ) ;
426+ if !is_interface_or_namespace {
427+ return false ;
428+ }
429+
416430 binding
417431 . syntax ( )
418432 . ancestors ( )
419433 . find_map ( JsModuleItemList :: cast)
420434 . is_some_and ( |module_list| {
421435 // Only check top-level declarations
422436 let is_top_level = module_list. parent :: < JsModule > ( ) . is_some ( ) ;
423-
424437 if !is_top_level {
425438 return false ;
426439 }
427440
428- // Presence of imports/exports means its a module
429- let has_import_or_export = ( & module_list) . into_iter ( ) . any ( |item| {
441+ // If there are imports/exports, it's a module, not a script
442+ ! module_list. into_iter ( ) . any ( |item| {
430443 let kind = item. syntax ( ) . kind ( ) ;
431444 JsImport :: can_cast ( kind) || JsExport :: can_cast ( kind)
432- } ) ;
433-
434- if has_import_or_export {
435- return false ;
436- }
437-
438- // We can't determine if an interface/namespace augments a global just from syntax
439- // so all of them are treated the same
440- module_list. into_iter ( ) . any ( |item| {
441- let kind = item. syntax ( ) . kind ( ) ;
442- TsInterfaceDeclaration :: can_cast ( kind) || TsModuleDeclaration :: can_cast ( kind)
443445 } )
444446 } )
445447}
0 commit comments