@@ -223,15 +223,21 @@ def _collect_files(self) -> list[Path]:
223223
224224 # Filter out ignored directories
225225 dirs [:] = [
226- d for d in dirs
227- if not self .ignore_spec .match_file (f"{ rel_root } /{ d } /" if rel_root != "." else f"{ d } /" )
226+ d
227+ for d in dirs
228+ if not self .ignore_spec .match_file (
229+ f"{ rel_root } /{ d } /" if rel_root != "." else f"{ d } /"
230+ )
228231 ]
229232
230233 # Filter out non-included directories when include_spec is set
231234 if self .include_spec :
232235 dirs [:] = [
233- d for d in dirs
234- if self .include_spec .match_file (f"{ rel_root } /{ d } /" if rel_root != "." else f"{ d } /" )
236+ d
237+ for d in dirs
238+ if self .include_spec .match_file (
239+ f"{ rel_root } /{ d } /" if rel_root != "." else f"{ d } /"
240+ )
235241 ]
236242
237243 for fname in filenames :
@@ -250,10 +256,17 @@ def _collect_files(self) -> list[Path]:
250256 @staticmethod
251257 def _is_scannable_file (rel_path : str ) -> bool :
252258 """Check if a file should be scanned."""
253- return rel_path .endswith ((
254- ".ts" , ".tsx" , ".js" , ".jsx" ,
255- ".css" , ".scss" , ".module.css" ,
256- ))
259+ return rel_path .endswith (
260+ (
261+ ".ts" ,
262+ ".tsx" ,
263+ ".js" ,
264+ ".jsx" ,
265+ ".css" ,
266+ ".scss" ,
267+ ".module.css" ,
268+ )
269+ )
257270
258271 @staticmethod
259272 def _is_css_file (rel_path : str ) -> bool :
@@ -304,7 +317,9 @@ def _parse_imports(
304317 for m in _IMPORT_PATTERN .finditer (content ):
305318 # Named imports: import { Foo, Bar } from '...'
306319 if m .group (1 ):
307- names = [n .strip ().split (" as " )[0 ].strip () for n in m .group (1 ).split ("," )]
320+ names = [
321+ n .strip ().split (" as " )[0 ].strip () for n in m .group (1 ).split ("," )
322+ ]
308323 for name in names :
309324 if name :
310325 imports .setdefault (name , set ()).add (rel_path )
@@ -360,9 +375,21 @@ def _find_unused_exports(
360375 """Find exports that are never imported elsewhere."""
361376 # Special names that are entry points or conventions
362377 skip_names = {
363- "default" , "GET" , "POST" , "PUT" , "DELETE" , "PATCH" , "HEAD" , "OPTIONS" ,
364- "middleware" , "config" , "metadata" , "generateMetadata" ,
365- "loader" , "action" , "generateStaticParams" ,
378+ "default" ,
379+ "GET" ,
380+ "POST" ,
381+ "PUT" ,
382+ "DELETE" ,
383+ "PATCH" ,
384+ "HEAD" ,
385+ "OPTIONS" ,
386+ "middleware" ,
387+ "config" ,
388+ "metadata" ,
389+ "generateMetadata" ,
390+ "loader" ,
391+ "action" ,
392+ "generateStaticParams" ,
366393 }
367394
368395 for name , locations in exports .items ():
@@ -374,14 +401,16 @@ def _find_unused_exports(
374401 external_importers = importers - exporter_files
375402 if not external_importers :
376403 for file , line in locations :
377- result .findings .append (Finding (
378- file = file ,
379- line = line ,
380- name = name ,
381- category = "unused_export" ,
382- detail = f"Export '{ name } ' is never imported outside its defining file" ,
383- removable = True ,
384- ))
404+ result .findings .append (
405+ Finding (
406+ file = file ,
407+ line = line ,
408+ name = name ,
409+ category = "unused_export" ,
410+ detail = f"Export '{ name } ' is never imported outside its defining file" ,
411+ removable = True ,
412+ )
413+ )
385414
386415 def _find_dead_routes (
387416 self ,
@@ -394,7 +423,9 @@ def _find_dead_routes(
394423 return
395424
396425 # Build set of all route paths referenced in links
397- link_pattern = re .compile (r'(?:href|to|push|replace)\s*[=:]\s*["\'](/[^"\']*)["\']' )
426+ link_pattern = re .compile (
427+ r'(?:href|to|push|replace)\s*[=:]\s*["\'](/[^"\']*)["\']'
428+ )
398429 referenced_routes : set [str ] = set ()
399430
400431 for filepath in all_files :
@@ -420,14 +451,16 @@ def _find_dead_routes(
420451 # Dynamic routes are harder to prove dead — skip them
421452 continue
422453
423- result .findings .append (Finding (
424- file = rel_path ,
425- line = 1 ,
426- name = route_path ,
427- category = "dead_route" ,
428- detail = f"Route '{ route_path } ' has no internal links pointing to it" ,
429- removable = False , # Routes may be linked externally
430- ))
454+ result .findings .append (
455+ Finding (
456+ file = rel_path ,
457+ line = 1 ,
458+ name = route_path ,
459+ category = "dead_route" ,
460+ detail = f"Route '{ route_path } ' has no internal links pointing to it" ,
461+ removable = False , # Routes may be linked externally
462+ )
463+ )
431464
432465 def _find_orphaned_css (
433466 self ,
@@ -438,19 +471,33 @@ def _find_orphaned_css(
438471 """Find CSS classes defined but never used in JSX."""
439472 for cls , locations in css_classes .items ():
440473 # Skip common utility classes and pseudo-selectors
441- if cls .startswith (("hover:" , "focus:" , "active:" , "disabled:" , "group-" , "sm:" , "md:" , "lg:" , "xl:" )):
474+ if cls .startswith (
475+ (
476+ "hover:" ,
477+ "focus:" ,
478+ "active:" ,
479+ "disabled:" ,
480+ "group-" ,
481+ "sm:" ,
482+ "md:" ,
483+ "lg:" ,
484+ "xl:" ,
485+ )
486+ ):
442487 continue
443488 if cls in used_css_classes :
444489 continue
445490 for file , line in locations :
446- result .findings .append (Finding (
447- file = file ,
448- line = line ,
449- name = cls ,
450- category = "orphaned_css" ,
451- detail = f"CSS class '.{ cls } ' is not used in any JSX className" ,
452- removable = True ,
453- ))
491+ result .findings .append (
492+ Finding (
493+ file = file ,
494+ line = line ,
495+ name = cls ,
496+ category = "orphaned_css" ,
497+ detail = f"CSS class '.{ cls } ' is not used in any JSX className" ,
498+ removable = True ,
499+ )
500+ )
454501
455502 def _find_unreferenced_components (
456503 self ,
@@ -460,7 +507,15 @@ def _find_unreferenced_components(
460507 ) -> None :
461508 """Find React components that are defined but never imported."""
462509 # Skip page/layout components (Next.js convention)
463- skip_suffixes = ("Page" , "Layout" , "Template" , "Loading" , "Error" , "NotFound" , "GlobalError" )
510+ skip_suffixes = (
511+ "Page" ,
512+ "Layout" ,
513+ "Template" ,
514+ "Loading" ,
515+ "Error" ,
516+ "NotFound" ,
517+ "GlobalError" ,
518+ )
464519
465520 for comp_name , file in components .items ():
466521 # Skip Next.js special files
@@ -473,11 +528,13 @@ def _find_unreferenced_components(
473528 if "/page." in file or "/route." in file or "/layout." in file :
474529 continue
475530
476- result .findings .append (Finding (
477- file = file ,
478- line = 1 ,
479- name = comp_name ,
480- category = "unreferenced_component" ,
481- detail = f"Component '{ comp_name } ' is never imported by other files" ,
482- removable = True ,
483- ))
531+ result .findings .append (
532+ Finding (
533+ file = file ,
534+ line = 1 ,
535+ name = comp_name ,
536+ category = "unreferenced_component" ,
537+ detail = f"Component '{ comp_name } ' is never imported by other files" ,
538+ removable = True ,
539+ )
540+ )
0 commit comments