Skip to content

Conversation

@michaelversus
Copy link
Owner

Remove Unnecessary @testable Imports & CLI Restructure

🎯 Overview

This PR introduces a major new feature to automatically detect and remove unnecessary @testable import statements from Swift test files, while also restructuring the CLI to use subcommands for better extensibility.

🚨 Breaking Changes

CLI Structure Migration

  • Breaking: --verbose is now a flag (no value required) instead of an option.
    • Before: swiftfindrefs --verbose true
    • After: swiftfindrefs search -v or swiftfindrefs search --verbose

✨ New Features

Remove Unnecessary Testable Imports Subcommand

  • New subcommand: removeUnnecessaryTestableImports (alias: rmUTI)
  • Automatically detects and removes @testable import statements that are no longer needed
  • Analyzes IndexStoreDB to determine if symbols are actually public (and thus don't require @testable)
  • Supports conditional compilation block exclusion via --excludeCompilationConditionals flag

Example usage:

swiftfindrefs removeUnnecessaryTestableImports --projectName MyApp --verbose --excludeCompilationConditionals
# or using the alias:
swiftfindrefs rmUTI -p MyApp -v --excludeCompilationConditionals

Conditional Compilation Support

  • New --excludeCompilationConditionals flag to exclude @testable import statements inside #if/#elseif/#else/#endif blocks
  • Useful for multi-target apps where different modules are imported based on build configuration

⚡ Performance Improvements

Async/Await Migration

  • Migrated core analysis and rewriting logic to async/await for better concurrency
  • Uses TaskGroup for parallel processing of files and units
  • Leverages URL.resourceBytes.lines for efficient async file reading

Optimizations

  • Lazy file reading: Files are only read when needed (during isPublic checks), not upfront
  • Module indexing: Units are indexed by module name to avoid O(n²) scans
  • Parallel rewriting: Multiple files are rewritten concurrently using TaskGroup

Performance impact: ~35% faster real-time execution and ~94% reduction in CPU time for large codebases.

📚 Documentation Updates

README

  • Updated to reflect new subcommand structure
  • Added documentation for removeUnnecessaryTestableImports subcommand
  • Added usage examples and performance notes
  • Expanded "How it works" section

Agent Skill Documentation

  • Updated SKILL.md with new command structure
  • Updated cli.md with subcommand details
  • Updated workflows.md with corrected examples
  • Updated troubleshooting.md with new command format

🔧 Technical Details

File System Operations

  • Added async readLines(atPath:) method to FileSystemProvider
  • Implemented using URL.resourceBytes.lines for efficient async reading
  • Added readFile and writeFile methods with comprehensive tests

IndexStore Integration

  • Extended IndexStoreProviding protocol with additional methods
  • Created snapshot types (UnitSnapshot, OccurrenceSnapshot) for thread-safe concurrent processing
  • Implemented lazy caching for file lines to minimize I/O

🎯 Migration Guide

For users upgrading from previous versions:

  1. Update verbose flag:

    # Old
    swiftfindrefs --verbose true
    
    # New
    swiftfindrefs -v
  2. Try the new feature:

    swiftfindrefs rmUTI -p MyApp -v

@michaelversus michaelversus added the enhancement New feature or request label Jan 15, 2026
@michaelversus michaelversus self-assigned this Jan 15, 2026
@codecov-commenter
Copy link

Codecov Report

❌ Patch coverage is 88.55835% with 100 lines in your changes missing coverage. Please review.
✅ Project coverage is 93.19%. Comparing base (3972433) to head (4e6d1ad).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
Sources/SwiftFindRefs/SwiftFindRefs.swift 0.00% 49 Missing ⚠️
...ecessaryTestable/UnnecessaryTestableAnalyzer.swift 89.30% 17 Missing ⚠️
...wiftFindRefs/IndexStore/IndexStore+Providing.swift 0.00% 7 Missing ⚠️
Tests/SwiftFindRefs/Mocks/MockFileSystem.swift 65.00% 7 Missing ⚠️
...saryTestable/UnnecessaryTestableRemoverTests.swift 89.06% 7 Missing ⚠️
...aryTestable/UnnecessaryTestableAnalyzerTests.swift 97.04% 6 Missing ⚠️
...s/CompositionRoot/RemoveCompositionRootTests.swift 96.15% 3 Missing ⚠️
...iftFindRefs/IndexStore/IndexStoreFinderTests.swift 84.61% 2 Missing ⚠️
...necessaryTestable/UnnecessaryTestableRemover.swift 94.73% 1 Missing ⚠️
...ecessaryTestable/UnnecessaryTestableRewriter.swift 97.14% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master       #5      +/-   ##
==========================================
- Coverage   95.47%   93.19%   -2.28%     
==========================================
  Files          20       32      +12     
  Lines        1082     1926     +844     
==========================================
+ Hits         1033     1795     +762     
- Misses         49      131      +82     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@michaelversus michaelversus merged commit ea0cd51 into master Jan 16, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants